winbind_nss_freebsd: fix const discard warning
[Samba.git] / source3 / smbd / smb2_server.c
blob68a024f4ec8103eb3c4faa6fa1d9f0f59a9b171e
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 static void smbd_smb2_connection_handler(struct tevent_context *ev,
36 struct tevent_fd *fde,
37 uint16_t flags,
38 void *private_data);
39 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
41 static const struct smbd_smb2_dispatch_table {
42 uint16_t opcode;
43 const char *name;
44 bool need_session;
45 bool need_tcon;
46 bool as_root;
47 uint16_t fileid_ofs;
48 bool allow_invalid_fileid;
49 bool modify;
50 } smbd_smb2_table[] = {
51 #define _OP(o) .opcode = o, .name = #o
53 _OP(SMB2_OP_NEGPROT),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_SESSSETUP),
57 .as_root = true,
58 },{
59 _OP(SMB2_OP_LOGOFF),
60 .need_session = true,
61 .as_root = true,
62 },{
63 _OP(SMB2_OP_TCON),
64 .need_session = true,
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
72 .as_root = true,
73 },{
74 _OP(SMB2_OP_TDIS),
75 .need_session = true,
76 .need_tcon = true,
77 .as_root = true,
78 },{
79 _OP(SMB2_OP_CREATE),
80 .need_session = true,
81 .need_tcon = true,
82 },{
83 _OP(SMB2_OP_CLOSE),
84 .need_session = true,
85 .need_tcon = true,
86 .fileid_ofs = 0x08,
87 },{
88 _OP(SMB2_OP_FLUSH),
89 .need_session = true,
90 .need_tcon = true,
91 .fileid_ofs = 0x08,
92 },{
93 _OP(SMB2_OP_READ),
94 .need_session = true,
95 .need_tcon = true,
96 .fileid_ofs = 0x10,
97 },{
98 _OP(SMB2_OP_WRITE),
99 .need_session = true,
100 .need_tcon = true,
101 .fileid_ofs = 0x10,
102 .modify = true,
104 _OP(SMB2_OP_LOCK),
105 .need_session = true,
106 .need_tcon = true,
107 .fileid_ofs = 0x08,
109 _OP(SMB2_OP_IOCTL),
110 .need_session = true,
111 .need_tcon = true,
112 .fileid_ofs = 0x08,
113 .allow_invalid_fileid = true,
114 .modify = true,
116 _OP(SMB2_OP_CANCEL),
117 .as_root = true,
119 _OP(SMB2_OP_KEEPALIVE),
120 .as_root = true,
122 _OP(SMB2_OP_QUERY_DIRECTORY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_NOTIFY),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x08,
132 _OP(SMB2_OP_GETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x18,
137 _OP(SMB2_OP_SETINFO),
138 .need_session = true,
139 .need_tcon = true,
140 .fileid_ofs = 0x10,
141 .modify = true,
143 _OP(SMB2_OP_BREAK),
144 .need_session = true,
145 .need_tcon = true,
147 * we do not set
148 * .fileid_ofs here
149 * as LEASE breaks does not
150 * have a file id
155 const char *smb2_opcode_name(uint16_t opcode)
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return "Bad SMB2 opcode";
160 return smbd_smb2_table[opcode].name;
163 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
165 const struct smbd_smb2_dispatch_table *ret = NULL;
167 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
168 return NULL;
171 ret = &smbd_smb2_table[opcode];
173 SMB_ASSERT(ret->opcode == opcode);
175 return ret;
178 static void print_req_vectors(const struct smbd_smb2_request *req)
180 int i;
182 for (i = 0; i < req->in.vector_count; i++) {
183 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
184 (unsigned int)i,
185 (unsigned int)req->in.vector[i].iov_len);
187 for (i = 0; i < req->out.vector_count; i++) {
188 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
189 (unsigned int)i,
190 (unsigned int)req->out.vector[i].iov_len);
194 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
196 if (size < (4 + SMB2_HDR_BODY)) {
197 return false;
200 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
201 return false;
204 return true;
207 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
209 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
212 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
213 uint64_t expected_seq_low)
215 TALLOC_FREE(xconn->transport.fde);
217 xconn->smb2.credits.seq_low = expected_seq_low;
218 xconn->smb2.credits.seq_range = 1;
219 xconn->smb2.credits.granted = 1;
220 xconn->smb2.credits.max = lp_smb2_max_credits();
221 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
222 xconn->smb2.credits.max);
223 if (xconn->smb2.credits.bitmap == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
228 xconn,
229 xconn->transport.sock,
230 TEVENT_FD_READ,
231 smbd_smb2_connection_handler,
232 xconn);
233 if (xconn->transport.fde == NULL) {
234 return NT_STATUS_NO_MEMORY;
237 /* Ensure child is set to non-blocking mode */
238 set_blocking(xconn->transport.sock, false);
239 return NT_STATUS_OK;
242 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
243 #define _smb2_setlen(_buf,len) do { \
244 uint8_t *buf = (uint8_t *)_buf; \
245 buf[0] = 0; \
246 buf[1] = ((len)&0xFF0000)>>16; \
247 buf[2] = ((len)&0xFF00)>>8; \
248 buf[3] = (len)&0xFF; \
249 } while (0)
251 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
253 ssize_t len;
255 if (count == 0) {
256 return false;
259 len = iov_buflen(vector+1, count-1);
261 if ((len == -1) || (len > 0xFFFFFF)) {
262 return false;
265 _smb2_setlen(vector[0].iov_base, len);
266 return true;
269 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
271 if (req->first_key.length > 0) {
272 data_blob_clear_free(&req->first_key);
274 if (req->last_key.length > 0) {
275 data_blob_clear_free(&req->last_key);
277 return 0;
280 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
281 bool async_internal)
283 req->async_internal = async_internal;
286 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
288 TALLOC_CTX *mem_pool;
289 struct smbd_smb2_request *req;
291 #if 0
292 /* Enable this to find subtle valgrind errors. */
293 mem_pool = talloc_init("smbd_smb2_request_allocate");
294 #else
295 mem_pool = talloc_tos();
296 #endif
297 if (mem_pool == NULL) {
298 return NULL;
301 req = talloc_zero(mem_pool, struct smbd_smb2_request);
302 if (req == NULL) {
303 talloc_free(mem_pool);
304 return NULL;
306 talloc_reparent(mem_pool, mem_ctx, req);
307 #if 0
308 TALLOC_FREE(mem_pool);
309 #endif
311 req->last_session_id = UINT64_MAX;
312 req->last_tid = UINT32_MAX;
314 talloc_set_destructor(req, smbd_smb2_request_destructor);
316 return req;
319 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
320 NTTIME now,
321 uint8_t *buf,
322 size_t buflen,
323 struct smbd_smb2_request *req,
324 struct iovec **piov,
325 int *pnum_iov)
327 TALLOC_CTX *mem_ctx = req;
328 struct iovec *iov;
329 int num_iov = 1;
330 size_t taken = 0;
331 uint8_t *first_hdr = buf;
332 size_t verified_buflen = 0;
333 uint8_t *tf = NULL;
334 size_t tf_len = 0;
337 * Note: index '0' is reserved for the transport protocol
339 iov = req->in._vector;
341 while (taken < buflen) {
342 size_t len = buflen - taken;
343 uint8_t *hdr = first_hdr + taken;
344 struct iovec *cur;
345 size_t full_size;
346 size_t next_command_ofs;
347 uint16_t body_size;
348 uint8_t *body = NULL;
349 uint32_t dyn_size;
350 uint8_t *dyn = NULL;
351 struct iovec *iov_alloc = NULL;
353 if (iov != req->in._vector) {
354 iov_alloc = iov;
357 if (verified_buflen > taken) {
358 len = verified_buflen - taken;
359 } else {
360 tf = NULL;
361 tf_len = 0;
364 if (len < 4) {
365 DEBUG(10, ("%d bytes left, expected at least %d\n",
366 (int)len, 4));
367 goto inval;
369 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
370 struct smbXsrv_session *s = NULL;
371 uint64_t uid;
372 struct iovec tf_iov[2];
373 NTSTATUS status;
374 size_t enc_len;
376 if (xconn->protocol < PROTOCOL_SMB2_24) {
377 DEBUG(10, ("Got SMB2_TRANSFORM header, "
378 "but dialect[0x%04X] is used\n",
379 xconn->smb2.server.dialect));
380 goto inval;
383 if (xconn->smb2.server.cipher == 0) {
384 DEBUG(10, ("Got SMB2_TRANSFORM header, "
385 "but not negotiated "
386 "client[0x%08X] server[0x%08X]\n",
387 xconn->smb2.client.capabilities,
388 xconn->smb2.server.capabilities));
389 goto inval;
392 if (len < SMB2_TF_HDR_SIZE) {
393 DEBUG(1, ("%d bytes left, expected at least %d\n",
394 (int)len, SMB2_TF_HDR_SIZE));
395 goto inval;
397 tf = hdr;
398 tf_len = SMB2_TF_HDR_SIZE;
399 taken += tf_len;
401 hdr = first_hdr + taken;
402 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
403 uid = BVAL(tf, SMB2_TF_SESSION_ID);
405 if (len < SMB2_TF_HDR_SIZE + enc_len) {
406 DEBUG(1, ("%d bytes left, expected at least %d\n",
407 (int)len,
408 (int)(SMB2_TF_HDR_SIZE + enc_len)));
409 goto inval;
412 status = smb2srv_session_lookup_conn(xconn, uid, now,
413 &s);
414 if (s == NULL) {
415 DEBUG(1, ("invalid session[%llu] in "
416 "SMB2_TRANSFORM header\n",
417 (unsigned long long)uid));
418 TALLOC_FREE(iov_alloc);
419 return NT_STATUS_USER_SESSION_DELETED;
422 tf_iov[0].iov_base = (void *)tf;
423 tf_iov[0].iov_len = tf_len;
424 tf_iov[1].iov_base = (void *)hdr;
425 tf_iov[1].iov_len = enc_len;
427 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
428 xconn->smb2.server.cipher,
429 tf_iov, 2);
430 if (!NT_STATUS_IS_OK(status)) {
431 TALLOC_FREE(iov_alloc);
432 return status;
435 verified_buflen = taken + enc_len;
436 len = enc_len;
440 * We need the header plus the body length field
443 if (len < SMB2_HDR_BODY + 2) {
444 DEBUG(10, ("%d bytes left, expected at least %d\n",
445 (int)len, SMB2_HDR_BODY));
446 goto inval;
448 if (IVAL(hdr, 0) != SMB2_MAGIC) {
449 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
450 IVAL(hdr, 0)));
451 goto inval;
453 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
454 DEBUG(10, ("Got HDR len %d, expected %d\n",
455 SVAL(hdr, 4), SMB2_HDR_BODY));
456 goto inval;
459 full_size = len;
460 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
461 body_size = SVAL(hdr, SMB2_HDR_BODY);
463 if (next_command_ofs != 0) {
464 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
465 goto inval;
467 if (next_command_ofs > full_size) {
468 goto inval;
470 full_size = next_command_ofs;
472 if (body_size < 2) {
473 goto inval;
475 body_size &= 0xfffe;
477 if (body_size > (full_size - SMB2_HDR_BODY)) {
479 * let the caller handle the error
481 body_size = full_size - SMB2_HDR_BODY;
483 body = hdr + SMB2_HDR_BODY;
484 dyn = body + body_size;
485 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
487 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
488 struct iovec *iov_tmp = NULL;
490 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
491 struct iovec,
492 num_iov +
493 SMBD_SMB2_NUM_IOV_PER_REQ);
494 if (iov_tmp == NULL) {
495 TALLOC_FREE(iov_alloc);
496 return NT_STATUS_NO_MEMORY;
499 if (iov_alloc == NULL) {
500 memcpy(iov_tmp,
501 req->in._vector,
502 sizeof(req->in._vector));
505 iov = iov_tmp;
507 cur = &iov[num_iov];
508 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
510 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
511 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
512 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
513 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
514 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
515 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
516 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
517 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
519 taken += full_size;
522 *piov = iov;
523 *pnum_iov = num_iov;
524 return NT_STATUS_OK;
526 inval:
527 if (iov != req->in._vector) {
528 TALLOC_FREE(iov);
530 return NT_STATUS_INVALID_PARAMETER;
533 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
534 const uint8_t *_inpdu, size_t size,
535 struct smbd_smb2_request **_req)
537 struct smbd_server_connection *sconn = xconn->client->sconn;
538 struct smbd_smb2_request *req;
539 uint32_t protocol_version;
540 uint8_t *inpdu = NULL;
541 const uint8_t *inhdr = NULL;
542 uint16_t cmd;
543 uint32_t next_command_ofs;
544 NTSTATUS status;
545 NTTIME now;
547 if (size < (SMB2_HDR_BODY + 2)) {
548 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
549 return NT_STATUS_INVALID_PARAMETER;
552 inhdr = _inpdu;
554 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
555 if (protocol_version != SMB2_MAGIC) {
556 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
557 protocol_version));
558 return NT_STATUS_INVALID_PARAMETER;
561 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
562 if (cmd != SMB2_OP_NEGPROT) {
563 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
564 cmd));
565 return NT_STATUS_INVALID_PARAMETER;
568 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
569 if (next_command_ofs != 0) {
570 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
571 next_command_ofs));
572 return NT_STATUS_INVALID_PARAMETER;
575 req = smbd_smb2_request_allocate(xconn);
576 if (req == NULL) {
577 return NT_STATUS_NO_MEMORY;
579 req->sconn = sconn;
580 req->xconn = xconn;
582 inpdu = talloc_memdup(req, _inpdu, size);
583 if (inpdu == NULL) {
584 return NT_STATUS_NO_MEMORY;
587 req->request_time = timeval_current();
588 now = timeval_to_nttime(&req->request_time);
590 status = smbd_smb2_inbuf_parse_compound(xconn,
591 now,
592 inpdu,
593 size,
594 req, &req->in.vector,
595 &req->in.vector_count);
596 if (!NT_STATUS_IS_OK(status)) {
597 TALLOC_FREE(req);
598 return status;
601 req->current_idx = 1;
603 *_req = req;
604 return NT_STATUS_OK;
607 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
608 uint64_t message_id, uint64_t seq_id)
610 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
611 unsigned int offset;
612 uint64_t seq_tmp;
614 seq_tmp = xconn->smb2.credits.seq_low;
615 if (seq_id < seq_tmp) {
616 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
617 "%llu (sequence id %llu) "
618 "(granted = %u, low = %llu, range = %u)\n",
619 (unsigned long long)message_id,
620 (unsigned long long)seq_id,
621 (unsigned int)xconn->smb2.credits.granted,
622 (unsigned long long)xconn->smb2.credits.seq_low,
623 (unsigned int)xconn->smb2.credits.seq_range));
624 return false;
627 seq_tmp += xconn->smb2.credits.seq_range;
628 if (seq_id >= seq_tmp) {
629 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
630 "%llu (sequence id %llu) "
631 "(granted = %u, low = %llu, range = %u)\n",
632 (unsigned long long)message_id,
633 (unsigned long long)seq_id,
634 (unsigned int)xconn->smb2.credits.granted,
635 (unsigned long long)xconn->smb2.credits.seq_low,
636 (unsigned int)xconn->smb2.credits.seq_range));
637 return false;
640 offset = seq_id % xconn->smb2.credits.max;
642 if (bitmap_query(credits_bm, offset)) {
643 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
644 "%llu (sequence id %llu) "
645 "(granted = %u, low = %llu, range = %u) "
646 "(bm offset %u)\n",
647 (unsigned long long)message_id,
648 (unsigned long long)seq_id,
649 (unsigned int)xconn->smb2.credits.granted,
650 (unsigned long long)xconn->smb2.credits.seq_low,
651 (unsigned int)xconn->smb2.credits.seq_range,
652 offset));
653 return false;
656 /* Mark the message_ids as seen in the bitmap. */
657 bitmap_set(credits_bm, offset);
659 if (seq_id != xconn->smb2.credits.seq_low) {
660 return true;
664 * Move the window forward by all the message_id's
665 * already seen.
667 while (bitmap_query(credits_bm, offset)) {
668 DEBUG(10,("smb2_validate_sequence_number: clearing "
669 "id %llu (position %u) from bitmap\n",
670 (unsigned long long)(xconn->smb2.credits.seq_low),
671 offset));
672 bitmap_clear(credits_bm, offset);
674 xconn->smb2.credits.seq_low += 1;
675 xconn->smb2.credits.seq_range -= 1;
676 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
679 return true;
682 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
683 const uint8_t *inhdr)
685 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
686 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
687 uint16_t credit_charge = 1;
688 uint64_t i;
690 if (opcode == SMB2_OP_CANCEL) {
691 /* SMB2_CANCEL requests by definition resend messageids. */
692 return true;
695 if (xconn->smb2.credits.multicredit) {
696 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
697 credit_charge = MAX(credit_charge, 1);
700 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
701 "credits_granted %llu, "
702 "seqnum low/range: %llu/%llu\n",
703 (unsigned long long) message_id,
704 (unsigned long long) credit_charge,
705 (unsigned long long) xconn->smb2.credits.granted,
706 (unsigned long long) xconn->smb2.credits.seq_low,
707 (unsigned long long) xconn->smb2.credits.seq_range));
709 if (xconn->smb2.credits.granted < credit_charge) {
710 DEBUG(0, ("smb2_validate_message_id: client used more "
711 "credits than granted, mid %llu, charge %llu, "
712 "credits_granted %llu, "
713 "seqnum low/range: %llu/%llu\n",
714 (unsigned long long) message_id,
715 (unsigned long long) credit_charge,
716 (unsigned long long) xconn->smb2.credits.granted,
717 (unsigned long long) xconn->smb2.credits.seq_low,
718 (unsigned long long) xconn->smb2.credits.seq_range));
719 return false;
723 * now check the message ids
725 * for multi-credit requests we need to check all current mid plus
726 * the implicit mids caused by the credit charge
727 * e.g. current mid = 15, charge 5 => mark 15-19 as used
730 for (i = 0; i <= (credit_charge-1); i++) {
731 uint64_t id = message_id + i;
732 bool ok;
734 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
735 (unsigned long long)message_id,
736 credit_charge,
737 (unsigned long long)id));
739 ok = smb2_validate_sequence_number(xconn, message_id, id);
740 if (!ok) {
741 return false;
745 /* substract used credits */
746 xconn->smb2.credits.granted -= credit_charge;
748 return true;
751 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
753 int count;
754 int idx;
756 count = req->in.vector_count;
758 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
759 /* It's not a SMB2 request */
760 return NT_STATUS_INVALID_PARAMETER;
763 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
764 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
765 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
766 const uint8_t *inhdr = NULL;
768 if (hdr->iov_len != SMB2_HDR_BODY) {
769 return NT_STATUS_INVALID_PARAMETER;
772 if (body->iov_len < 2) {
773 return NT_STATUS_INVALID_PARAMETER;
776 inhdr = (const uint8_t *)hdr->iov_base;
778 /* Check the SMB2 header */
779 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
780 return NT_STATUS_INVALID_PARAMETER;
783 if (!smb2_validate_message_id(req->xconn, inhdr)) {
784 return NT_STATUS_INVALID_PARAMETER;
788 return NT_STATUS_OK;
791 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
792 const struct iovec *in_vector,
793 struct iovec *out_vector)
795 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
796 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
797 uint16_t credit_charge = 1;
798 uint16_t credits_requested;
799 uint32_t out_flags;
800 uint16_t cmd;
801 NTSTATUS out_status;
802 uint16_t credits_granted = 0;
803 uint64_t credits_possible;
804 uint16_t current_max_credits;
807 * first we grant only 1/16th of the max range.
809 * Windows also starts with the 1/16th and then grants
810 * more later. I was only able to trigger higher
811 * values, when using a very high credit charge.
813 * TODO: scale up depending on load, free memory
814 * or other stuff.
815 * Maybe also on the relationship between number
816 * of requests and the used sequence number.
817 * Which means we would grant more credits
818 * for client which use multi credit requests.
820 current_max_credits = xconn->smb2.credits.max / 16;
821 current_max_credits = MAX(current_max_credits, 1);
823 if (xconn->smb2.credits.multicredit) {
824 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
825 credit_charge = MAX(credit_charge, 1);
828 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
829 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
830 credits_requested = MAX(credits_requested, 1);
831 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
832 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
834 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
836 if (xconn->smb2.credits.max < credit_charge) {
837 smbd_server_connection_terminate(xconn,
838 "client error: credit charge > max credits\n");
839 return;
842 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
844 * In case we already send an async interim
845 * response, we should not grant
846 * credits on the final response.
848 credits_granted = 0;
849 } else {
850 uint16_t additional_possible =
851 xconn->smb2.credits.max - credit_charge;
852 uint16_t additional_max = 0;
853 uint16_t additional_credits = credits_requested - 1;
855 switch (cmd) {
856 case SMB2_OP_NEGPROT:
857 break;
858 case SMB2_OP_SESSSETUP:
860 * Windows 2012 RC1 starts to grant
861 * additional credits
862 * with a successful session setup
864 if (NT_STATUS_IS_OK(out_status)) {
865 additional_max = 32;
867 break;
868 default:
870 * We match windows and only grant additional credits
871 * in chunks of 32.
873 additional_max = 32;
874 break;
877 additional_max = MIN(additional_max, additional_possible);
878 additional_credits = MIN(additional_credits, additional_max);
880 credits_granted = credit_charge + additional_credits;
884 * sequence numbers should not wrap
886 * 1. calculate the possible credits until
887 * the sequence numbers start to wrap on 64-bit.
889 * 2. UINT64_MAX is used for Break Notifications.
891 * 2. truncate the possible credits to the maximum
892 * credits we want to grant to the client in total.
894 * 3. remove the range we'll already granted to the client
895 * this makes sure the client consumes the lowest sequence
896 * number, before we can grant additional credits.
898 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
899 if (credits_possible > 0) {
900 /* remove UINT64_MAX */
901 credits_possible -= 1;
903 credits_possible = MIN(credits_possible, current_max_credits);
904 credits_possible -= xconn->smb2.credits.seq_range;
906 credits_granted = MIN(credits_granted, credits_possible);
908 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
909 xconn->smb2.credits.granted += credits_granted;
910 xconn->smb2.credits.seq_range += credits_granted;
912 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
913 "granted %u, current possible/max %u/%u, "
914 "total granted/max/low/range %u/%u/%llu/%u\n",
915 (unsigned int)credits_requested,
916 (unsigned int)credit_charge,
917 (unsigned int)credits_granted,
918 (unsigned int)credits_possible,
919 (unsigned int)current_max_credits,
920 (unsigned int)xconn->smb2.credits.granted,
921 (unsigned int)xconn->smb2.credits.max,
922 (unsigned long long)xconn->smb2.credits.seq_low,
923 (unsigned int)xconn->smb2.credits.seq_range));
926 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
927 struct smbd_smb2_request *outreq)
929 int count, idx;
930 uint16_t total_credits = 0;
932 count = outreq->out.vector_count;
934 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
935 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
936 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
937 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
939 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
941 /* To match Windows, count up what we
942 just granted. */
943 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
944 /* Set to zero in all but the last reply. */
945 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
946 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
947 } else {
948 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
953 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
955 if (req->current_idx <= 1) {
956 if (size <= sizeof(req->out._body)) {
957 return data_blob_const(req->out._body, size);
961 return data_blob_talloc(req, NULL, size);
964 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
966 struct smbXsrv_connection *xconn = req->xconn;
967 TALLOC_CTX *mem_ctx;
968 struct iovec *vector;
969 int count;
970 int idx;
971 bool ok;
973 count = req->in.vector_count;
974 if (count <= ARRAY_SIZE(req->out._vector)) {
975 mem_ctx = req;
976 vector = req->out._vector;
977 } else {
978 vector = talloc_zero_array(req, struct iovec, count);
979 if (vector == NULL) {
980 return NT_STATUS_NO_MEMORY;
982 mem_ctx = vector;
985 vector[0].iov_base = req->out.nbt_hdr;
986 vector[0].iov_len = 4;
987 SIVAL(req->out.nbt_hdr, 0, 0);
989 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
990 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
991 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
992 uint8_t *outhdr = NULL;
993 uint8_t *outbody = NULL;
994 uint32_t next_command_ofs = 0;
995 struct iovec *current = &vector[idx];
997 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
998 /* we have a next command -
999 * setup for the error case. */
1000 next_command_ofs = SMB2_HDR_BODY + 9;
1003 if (idx == 1) {
1004 outhdr = req->out._hdr;
1005 } else {
1006 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1007 OUTVEC_ALLOC_SIZE);
1008 if (outhdr == NULL) {
1009 return NT_STATUS_NO_MEMORY;
1013 outbody = outhdr + SMB2_HDR_BODY;
1016 * SMBD_SMB2_TF_IOV_OFS might be used later
1018 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1019 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1021 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1022 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1024 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1025 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1027 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1028 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1030 /* setup the SMB2 header */
1031 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1032 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1033 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1034 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1035 SIVAL(outhdr, SMB2_HDR_STATUS,
1036 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1037 SSVAL(outhdr, SMB2_HDR_OPCODE,
1038 SVAL(inhdr, SMB2_HDR_OPCODE));
1039 SIVAL(outhdr, SMB2_HDR_FLAGS,
1040 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1041 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1042 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1043 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1044 SIVAL(outhdr, SMB2_HDR_PID,
1045 IVAL(inhdr, SMB2_HDR_PID));
1046 SIVAL(outhdr, SMB2_HDR_TID,
1047 IVAL(inhdr, SMB2_HDR_TID));
1048 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1049 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1050 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1051 inhdr + SMB2_HDR_SIGNATURE, 16);
1053 /* setup error body header */
1054 SSVAL(outbody, 0x00, 0x08 + 1);
1055 SSVAL(outbody, 0x02, 0);
1056 SIVAL(outbody, 0x04, 0);
1059 req->out.vector = vector;
1060 req->out.vector_count = count;
1062 /* setup the length of the NBT packet */
1063 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1064 if (!ok) {
1065 return NT_STATUS_INVALID_PARAMETER_MIX;
1068 DLIST_ADD_END(xconn->smb2.requests, req);
1070 return NT_STATUS_OK;
1073 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1074 const char *reason,
1075 const char *location)
1077 struct smbXsrv_client *client = xconn->client;
1079 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1080 smbXsrv_connection_dbg(xconn), reason, location));
1082 if (client->connections->next != NULL) {
1083 /* TODO: cancel pending requests */
1084 DLIST_REMOVE(client->connections, xconn);
1085 TALLOC_FREE(xconn);
1086 return;
1090 * The last connection was disconnected
1092 exit_server_cleanly(reason);
1095 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1096 struct iovec *outvec,
1097 const struct iovec *srcvec)
1099 const uint8_t *srctf;
1100 size_t srctf_len;
1101 const uint8_t *srchdr;
1102 size_t srchdr_len;
1103 const uint8_t *srcbody;
1104 size_t srcbody_len;
1105 const uint8_t *expected_srcbody;
1106 const uint8_t *srcdyn;
1107 size_t srcdyn_len;
1108 const uint8_t *expected_srcdyn;
1109 uint8_t *dsttf;
1110 uint8_t *dsthdr;
1111 uint8_t *dstbody;
1112 uint8_t *dstdyn;
1114 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1115 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1116 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1117 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1118 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1119 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1120 expected_srcbody = srchdr + SMB2_HDR_BODY;
1121 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1122 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1123 expected_srcdyn = srcbody + 8;
1125 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1126 return false;
1129 if (srchdr_len != SMB2_HDR_BODY) {
1130 return false;
1133 if (srctf_len == SMB2_TF_HDR_SIZE) {
1134 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1135 if (dsttf == NULL) {
1136 return false;
1138 } else {
1139 dsttf = NULL;
1141 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1142 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1144 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1145 * be allocated with size OUTVEC_ALLOC_SIZE. */
1147 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1148 if (dsthdr == NULL) {
1149 return false;
1151 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1152 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1155 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1156 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1157 * then duplicate this. Else use talloc_memdup().
1160 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1161 dstbody = dsthdr + SMB2_HDR_BODY;
1162 } else {
1163 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1164 if (dstbody == NULL) {
1165 return false;
1168 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1169 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1172 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1173 * pointing to
1174 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1175 * then duplicate this. Else use talloc_memdup().
1178 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1179 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1180 } else if (srcdyn == NULL) {
1181 dstdyn = NULL;
1182 } else {
1183 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1184 if (dstdyn == NULL) {
1185 return false;
1188 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1189 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1191 return true;
1194 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1196 struct smbd_smb2_request *newreq = NULL;
1197 struct iovec *outvec = NULL;
1198 int count = req->out.vector_count;
1199 int i;
1200 bool ok;
1202 newreq = smbd_smb2_request_allocate(req->xconn);
1203 if (!newreq) {
1204 return NULL;
1207 newreq->sconn = req->sconn;
1208 newreq->xconn = req->xconn;
1209 newreq->session = req->session;
1210 newreq->do_encryption = req->do_encryption;
1211 newreq->do_signing = req->do_signing;
1212 newreq->current_idx = req->current_idx;
1214 outvec = talloc_zero_array(newreq, struct iovec, count);
1215 if (!outvec) {
1216 TALLOC_FREE(newreq);
1217 return NULL;
1219 newreq->out.vector = outvec;
1220 newreq->out.vector_count = count;
1222 /* Setup the outvec's identically to req. */
1223 outvec[0].iov_base = newreq->out.nbt_hdr;
1224 outvec[0].iov_len = 4;
1225 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1227 /* Setup the vectors identically to the ones in req. */
1228 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1229 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1230 break;
1234 if (i < count) {
1235 /* Alloc failed. */
1236 TALLOC_FREE(newreq);
1237 return NULL;
1240 ok = smb2_setup_nbt_length(newreq->out.vector,
1241 newreq->out.vector_count);
1242 if (!ok) {
1243 TALLOC_FREE(newreq);
1244 return NULL;
1247 return newreq;
1250 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1252 struct smbXsrv_connection *xconn = req->xconn;
1253 int first_idx = 1;
1254 struct iovec *firsttf = NULL;
1255 struct iovec *outhdr_v = NULL;
1256 uint8_t *outhdr = NULL;
1257 struct smbd_smb2_request *nreq = NULL;
1258 NTSTATUS status;
1259 bool ok;
1261 /* Create a new smb2 request we'll use
1262 for the interim return. */
1263 nreq = dup_smb2_req(req);
1264 if (!nreq) {
1265 return NT_STATUS_NO_MEMORY;
1268 /* Lose the last X out vectors. They're the
1269 ones we'll be using for the async reply. */
1270 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1272 ok = smb2_setup_nbt_length(nreq->out.vector,
1273 nreq->out.vector_count);
1274 if (!ok) {
1275 return NT_STATUS_INVALID_PARAMETER_MIX;
1278 /* Step back to the previous reply. */
1279 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1280 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1281 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1282 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1283 /* And end the chain. */
1284 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1286 /* Calculate outgoing credits */
1287 smb2_calculate_credits(req, nreq);
1289 if (DEBUGLEVEL >= 10) {
1290 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1291 (unsigned int)nreq->current_idx );
1292 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1293 (unsigned int)nreq->out.vector_count );
1294 print_req_vectors(nreq);
1298 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1299 * we need to sign/encrypt here with the last/first key we remembered
1301 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1302 status = smb2_signing_encrypt_pdu(req->first_key,
1303 xconn->smb2.server.cipher,
1304 firsttf,
1305 nreq->out.vector_count - first_idx);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 return status;
1309 } else if (req->last_key.length > 0) {
1310 status = smb2_signing_sign_pdu(req->last_key,
1311 xconn->protocol,
1312 outhdr_v,
1313 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 return status;
1319 nreq->queue_entry.mem_ctx = nreq;
1320 nreq->queue_entry.vector = nreq->out.vector;
1321 nreq->queue_entry.count = nreq->out.vector_count;
1322 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1323 xconn->smb2.send_queue_len++;
1325 status = smbd_smb2_flush_send_queue(xconn);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 return status;
1330 return NT_STATUS_OK;
1333 struct smbd_smb2_request_pending_state {
1334 struct smbd_smb2_send_queue queue_entry;
1335 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1336 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1339 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1340 struct tevent_timer *te,
1341 struct timeval current_time,
1342 void *private_data);
1344 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1345 struct tevent_req *subreq,
1346 uint32_t defer_time)
1348 NTSTATUS status;
1349 struct timeval defer_endtime;
1350 uint8_t *outhdr = NULL;
1351 uint32_t flags;
1353 if (!tevent_req_is_in_progress(subreq)) {
1355 * This is a performance optimization,
1356 * it avoids one tevent_loop iteration,
1357 * which means we avoid one
1358 * talloc_stackframe_pool/talloc_free pair.
1360 tevent_req_notify_callback(subreq);
1361 return NT_STATUS_OK;
1364 req->subreq = subreq;
1365 subreq = NULL;
1367 if (req->async_te) {
1368 /* We're already async. */
1369 return NT_STATUS_OK;
1372 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1373 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1374 if (flags & SMB2_HDR_FLAG_ASYNC) {
1375 /* We're already async. */
1376 return NT_STATUS_OK;
1379 if (req->async_internal) {
1381 * An SMB2 request implementation wants to handle the request
1382 * asynchronously "internally" while keeping synchronous
1383 * behaviour for the SMB2 request. This means we don't send an
1384 * interim response and we can allow processing of compound SMB2
1385 * requests (cf the subsequent check) for all cases.
1387 return NT_STATUS_OK;
1390 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1392 * We're trying to go async in a compound request
1393 * chain. This is only allowed for opens that cause an
1394 * oplock break or for the last operation in the
1395 * chain, otherwise it is not allowed. See
1396 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1398 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1400 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1402 * Cancel the outstanding request.
1404 bool ok = tevent_req_cancel(req->subreq);
1405 if (ok) {
1406 return NT_STATUS_OK;
1408 TALLOC_FREE(req->subreq);
1409 return smbd_smb2_request_error(req,
1410 NT_STATUS_INTERNAL_ERROR);
1414 if (DEBUGLEVEL >= 10) {
1415 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1416 (unsigned int)req->current_idx );
1417 print_req_vectors(req);
1420 if (req->current_idx > 1) {
1422 * We're going async in a compound
1423 * chain after the first request has
1424 * already been processed. Send an
1425 * interim response containing the
1426 * set of replies already generated.
1428 int idx = req->current_idx;
1430 status = smb2_send_async_interim_response(req);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 return status;
1434 if (req->first_key.length > 0) {
1435 data_blob_clear_free(&req->first_key);
1438 req->current_idx = 1;
1441 * Re-arrange the in.vectors to remove what
1442 * we just sent.
1444 memmove(&req->in.vector[1],
1445 &req->in.vector[idx],
1446 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1447 req->in.vector_count = 1 + (req->in.vector_count - idx);
1449 /* Re-arrange the out.vectors to match. */
1450 memmove(&req->out.vector[1],
1451 &req->out.vector[idx],
1452 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1453 req->out.vector_count = 1 + (req->out.vector_count - idx);
1455 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1457 * We only have one remaining request as
1458 * we've processed everything else.
1459 * This is no longer a compound request.
1461 req->compound_related = false;
1462 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1463 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1464 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1467 if (req->last_key.length > 0) {
1468 data_blob_clear_free(&req->last_key);
1471 defer_endtime = timeval_current_ofs_usec(defer_time);
1472 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1473 req, defer_endtime,
1474 smbd_smb2_request_pending_timer,
1475 req);
1476 if (req->async_te == NULL) {
1477 return NT_STATUS_NO_MEMORY;
1480 return NT_STATUS_OK;
1483 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1484 struct smbXsrv_connection *xconn)
1486 struct smbXsrv_channel_global0 *c = NULL;
1487 NTSTATUS status;
1488 DATA_BLOB key = data_blob_null;
1490 status = smbXsrv_session_find_channel(session, xconn, &c);
1491 if (NT_STATUS_IS_OK(status)) {
1492 key = c->signing_key;
1495 if (key.length == 0) {
1496 key = session->global->signing_key;
1499 return key;
1502 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1503 uint64_t *new_nonce_high,
1504 uint64_t *new_nonce_low)
1506 uint64_t nonce_high;
1507 uint64_t nonce_low;
1509 session->nonce_low += 1;
1510 if (session->nonce_low == 0) {
1511 session->nonce_low += 1;
1512 session->nonce_high += 1;
1516 * CCM and GCM algorithms must never have their
1517 * nonce wrap, or the security of the whole
1518 * communication and the keys is destroyed.
1519 * We must drop the connection once we have
1520 * transfered too much data.
1522 * NOTE: We assume nonces greater than 8 bytes.
1524 if (session->nonce_high >= session->nonce_high_max) {
1525 return NT_STATUS_ENCRYPTION_FAILED;
1528 nonce_high = session->nonce_high_random;
1529 nonce_high += session->nonce_high;
1530 nonce_low = session->nonce_low;
1532 *new_nonce_high = nonce_high;
1533 *new_nonce_low = nonce_low;
1534 return NT_STATUS_OK;
1537 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1538 struct tevent_timer *te,
1539 struct timeval current_time,
1540 void *private_data)
1542 struct smbd_smb2_request *req =
1543 talloc_get_type_abort(private_data,
1544 struct smbd_smb2_request);
1545 struct smbXsrv_connection *xconn = req->xconn;
1546 struct smbd_smb2_request_pending_state *state = NULL;
1547 uint8_t *outhdr = NULL;
1548 const uint8_t *inhdr = NULL;
1549 uint8_t *tf = NULL;
1550 size_t tf_len = 0;
1551 uint8_t *hdr = NULL;
1552 uint8_t *body = NULL;
1553 uint8_t *dyn = NULL;
1554 uint32_t flags = 0;
1555 uint64_t session_id = 0;
1556 uint64_t message_id = 0;
1557 uint64_t nonce_high = 0;
1558 uint64_t nonce_low = 0;
1559 uint64_t async_id = 0;
1560 NTSTATUS status;
1561 bool ok;
1563 TALLOC_FREE(req->async_te);
1565 /* Ensure our final reply matches the interim one. */
1566 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1567 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1568 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1569 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1570 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1572 async_id = message_id; /* keep it simple for now... */
1574 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1575 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1577 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1578 "going async\n",
1579 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1580 (unsigned long long)async_id ));
1583 * What we send is identical to a smbd_smb2_request_error
1584 * packet with an error status of STATUS_PENDING. Make use
1585 * of this fact sometime when refactoring. JRA.
1588 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1589 if (state == NULL) {
1590 smbd_server_connection_terminate(xconn,
1591 nt_errstr(NT_STATUS_NO_MEMORY));
1592 return;
1595 tf = state->buf + NBT_HDR_SIZE;
1596 tf_len = SMB2_TF_HDR_SIZE;
1598 hdr = tf + SMB2_TF_HDR_SIZE;
1599 body = hdr + SMB2_HDR_BODY;
1600 dyn = body + 8;
1602 if (req->do_encryption) {
1603 status = smb2_get_new_nonce(req->session,
1604 &nonce_high,
1605 &nonce_low);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 smbd_server_connection_terminate(xconn,
1608 nt_errstr(status));
1609 return;
1613 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1614 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1615 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1616 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1618 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1619 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1620 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1621 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1622 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1624 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1625 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1626 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1627 SBVAL(hdr, SMB2_HDR_PID, async_id);
1628 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1629 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1630 memcpy(hdr+SMB2_HDR_SIGNATURE,
1631 outhdr+SMB2_HDR_SIGNATURE, 16);
1633 SSVAL(body, 0x00, 0x08 + 1);
1635 SCVAL(body, 0x02, 0);
1636 SCVAL(body, 0x03, 0);
1637 SIVAL(body, 0x04, 0);
1638 /* Match W2K8R2... */
1639 SCVAL(dyn, 0x00, 0x21);
1641 state->vector[0].iov_base = (void *)state->buf;
1642 state->vector[0].iov_len = NBT_HDR_SIZE;
1644 if (req->do_encryption) {
1645 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1646 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1647 } else {
1648 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1649 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1652 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1653 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1655 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1656 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1658 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1659 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1661 ok = smb2_setup_nbt_length(state->vector,
1662 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1663 if (!ok) {
1664 smbd_server_connection_terminate(
1665 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1666 return;
1669 /* Ensure we correctly go through crediting. Grant
1670 the credits now, and zero credits on the final
1671 response. */
1672 smb2_set_operation_credit(req->xconn,
1673 SMBD_SMB2_IN_HDR_IOV(req),
1674 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1676 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1678 if (DEBUGLVL(10)) {
1679 int i;
1681 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1682 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1683 (unsigned int)i,
1684 (unsigned int)ARRAY_SIZE(state->vector),
1685 (unsigned int)state->vector[i].iov_len);
1689 if (req->do_encryption) {
1690 struct smbXsrv_session *x = req->session;
1691 DATA_BLOB encryption_key = x->global->encryption_key;
1693 status = smb2_signing_encrypt_pdu(encryption_key,
1694 xconn->smb2.server.cipher,
1695 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1696 SMBD_SMB2_NUM_IOV_PER_REQ);
1697 if (!NT_STATUS_IS_OK(status)) {
1698 smbd_server_connection_terminate(xconn,
1699 nt_errstr(status));
1700 return;
1702 } else if (req->do_signing) {
1703 struct smbXsrv_session *x = req->session;
1704 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1706 status = smb2_signing_sign_pdu(signing_key,
1707 xconn->protocol,
1708 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1709 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 smbd_server_connection_terminate(xconn,
1712 nt_errstr(status));
1713 return;
1717 state->queue_entry.mem_ctx = state;
1718 state->queue_entry.vector = state->vector;
1719 state->queue_entry.count = ARRAY_SIZE(state->vector);
1720 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1721 xconn->smb2.send_queue_len++;
1723 status = smbd_smb2_flush_send_queue(xconn);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 smbd_server_connection_terminate(xconn,
1726 nt_errstr(status));
1727 return;
1731 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1733 struct smbXsrv_connection *xconn = req->xconn;
1734 struct smbd_smb2_request *cur;
1735 const uint8_t *inhdr;
1736 uint32_t flags;
1737 uint64_t search_message_id;
1738 uint64_t search_async_id;
1739 uint64_t found_id;
1741 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1743 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1744 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1745 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1748 * We don't need the request anymore cancel requests never
1749 * have a response.
1751 * We defer the TALLOC_FREE(req) to the caller.
1753 DLIST_REMOVE(xconn->smb2.requests, req);
1755 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1756 const uint8_t *outhdr;
1757 uint64_t message_id;
1758 uint64_t async_id;
1760 if (cur->compound_related) {
1762 * Never cancel anything in a compound request.
1763 * Way too hard to deal with the result.
1765 continue;
1768 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1770 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1771 async_id = BVAL(outhdr, SMB2_HDR_PID);
1773 if (flags & SMB2_HDR_FLAG_ASYNC) {
1774 if (search_async_id == async_id) {
1775 found_id = async_id;
1776 break;
1778 } else {
1779 if (search_message_id == message_id) {
1780 found_id = message_id;
1781 break;
1786 if (cur && cur->subreq) {
1787 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1788 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1789 "cancel opcode[%s] mid %llu\n",
1790 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1791 (unsigned long long)found_id ));
1792 tevent_req_cancel(cur->subreq);
1795 return NT_STATUS_OK;
1798 /*************************************************************
1799 Ensure an incoming tid is a valid one for us to access.
1800 Change to the associated uid credentials and chdir to the
1801 valid tid directory.
1802 *************************************************************/
1804 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1806 const uint8_t *inhdr;
1807 uint32_t in_flags;
1808 uint32_t in_tid;
1809 struct smbXsrv_tcon *tcon;
1810 NTSTATUS status;
1811 NTTIME now = timeval_to_nttime(&req->request_time);
1813 req->tcon = NULL;
1815 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1817 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1818 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1820 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1821 in_tid = req->last_tid;
1824 req->last_tid = 0;
1826 status = smb2srv_tcon_lookup(req->session,
1827 in_tid, now, &tcon);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 return status;
1832 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1833 return NT_STATUS_ACCESS_DENIED;
1836 if (!set_current_service(tcon->compat, 0, true)) {
1837 return NT_STATUS_ACCESS_DENIED;
1840 req->tcon = tcon;
1841 req->last_tid = in_tid;
1843 return NT_STATUS_OK;
1846 /*************************************************************
1847 Ensure an incoming session_id is a valid one for us to access.
1848 *************************************************************/
1850 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1852 const uint8_t *inhdr;
1853 uint32_t in_flags;
1854 uint16_t in_opcode;
1855 uint64_t in_session_id;
1856 struct smbXsrv_session *session = NULL;
1857 struct auth_session_info *session_info;
1858 NTSTATUS status;
1859 NTTIME now = timeval_to_nttime(&req->request_time);
1861 req->session = NULL;
1862 req->tcon = NULL;
1864 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1866 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1867 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1868 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1870 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1871 in_session_id = req->last_session_id;
1874 req->last_session_id = 0;
1876 /* look an existing session up */
1877 switch (in_opcode) {
1878 case SMB2_OP_SESSSETUP:
1880 * For a session bind request, we don't have the
1881 * channel set up at this point yet, so we defer
1882 * the verification that the connection belongs
1883 * to the session to the session setup code, which
1884 * can look at the session binding flags.
1886 status = smb2srv_session_lookup_client(req->xconn->client,
1887 in_session_id, now,
1888 &session);
1889 break;
1890 default:
1891 status = smb2srv_session_lookup_conn(req->xconn,
1892 in_session_id, now,
1893 &session);
1894 break;
1896 if (session) {
1897 req->session = session;
1898 req->last_session_id = in_session_id;
1900 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1901 switch (in_opcode) {
1902 case SMB2_OP_SESSSETUP:
1903 status = NT_STATUS_OK;
1904 break;
1905 default:
1906 break;
1909 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1910 switch (in_opcode) {
1911 case SMB2_OP_TCON:
1912 case SMB2_OP_CREATE:
1913 case SMB2_OP_GETINFO:
1914 case SMB2_OP_SETINFO:
1915 return NT_STATUS_INVALID_HANDLE;
1916 default:
1918 * Notice the check for
1919 * (session_info == NULL)
1920 * below.
1922 status = NT_STATUS_OK;
1923 break;
1926 if (!NT_STATUS_IS_OK(status)) {
1927 return status;
1930 session_info = session->global->auth_session_info;
1931 if (session_info == NULL) {
1932 return NT_STATUS_INVALID_HANDLE;
1935 if (in_session_id != req->xconn->client->last_session_id) {
1936 req->xconn->client->last_session_id = in_session_id;
1937 set_current_user_info(session_info->unix_info->sanitized_username,
1938 session_info->unix_info->unix_name,
1939 session_info->info->domain_name);
1942 return NT_STATUS_OK;
1945 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1946 uint32_t data_length)
1948 struct smbXsrv_connection *xconn = req->xconn;
1949 uint16_t needed_charge;
1950 uint16_t credit_charge = 1;
1951 const uint8_t *inhdr;
1953 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1955 if (xconn->smb2.credits.multicredit) {
1956 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1957 credit_charge = MAX(credit_charge, 1);
1960 needed_charge = (data_length - 1)/ 65536 + 1;
1962 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1963 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1964 credit_charge, needed_charge));
1966 if (needed_charge > credit_charge) {
1967 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1968 credit_charge, needed_charge));
1969 return NT_STATUS_INVALID_PARAMETER;
1972 return NT_STATUS_OK;
1975 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1976 size_t expected_body_size)
1978 struct iovec *inhdr_v;
1979 const uint8_t *inhdr;
1980 uint16_t opcode;
1981 const uint8_t *inbody;
1982 size_t body_size;
1983 size_t min_dyn_size = expected_body_size & 0x00000001;
1984 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1987 * The following should be checked already.
1989 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1990 return NT_STATUS_INTERNAL_ERROR;
1992 if (req->current_idx > max_idx) {
1993 return NT_STATUS_INTERNAL_ERROR;
1996 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1997 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1998 return NT_STATUS_INTERNAL_ERROR;
2000 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2001 return NT_STATUS_INTERNAL_ERROR;
2004 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2005 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2007 switch (opcode) {
2008 case SMB2_OP_IOCTL:
2009 case SMB2_OP_GETINFO:
2010 min_dyn_size = 0;
2011 break;
2012 case SMB2_OP_WRITE:
2013 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2014 if (req->smb1req->unread_bytes < min_dyn_size) {
2015 return NT_STATUS_INVALID_PARAMETER;
2018 min_dyn_size = 0;
2020 break;
2024 * Now check the expected body size,
2025 * where the last byte might be in the
2026 * dynamic section..
2028 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2029 return NT_STATUS_INVALID_PARAMETER;
2031 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2032 return NT_STATUS_INVALID_PARAMETER;
2035 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2037 body_size = SVAL(inbody, 0x00);
2038 if (body_size != expected_body_size) {
2039 return NT_STATUS_INVALID_PARAMETER;
2042 return NT_STATUS_OK;
2045 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2047 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2049 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2050 SMBXSRV_ENCRYPTION_DESIRED |
2051 SMBXSRV_ENCRYPTION_REQUIRED)));
2054 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2056 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2057 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2060 /* Set a flag if not already set, return true if set */
2061 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2063 if ((flag == 0) || (*flags & flag)) {
2064 return false;
2067 *flags |= flag;
2068 return true;
2072 * Update encryption state tracking flags, this can be used to
2073 * determine whether whether the session or tcon is "encrypted".
2075 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2076 uint16_t opcode,
2077 bool *update_session_globalp,
2078 bool *update_tcon_globalp)
2080 /* Default: assume unecrypted and unsigned */
2081 struct smbXsrv_session *session = req->session;
2082 struct smbXsrv_tcon *tcon = req->tcon;
2083 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2084 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2085 bool update_session = false;
2086 bool update_tcon = false;
2088 if (req->was_encrypted && req->do_encryption) {
2089 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2090 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2091 } else {
2092 /* Unencrypted packet, can be signed */
2093 if (req->do_signing) {
2094 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2095 } else if (opcode == SMB2_OP_CANCEL) {
2096 /* Cancel requests are allowed to skip signing */
2097 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2101 update_session |= smbXsrv_set_crypto_flag(
2102 &session->global->encryption_flags, encrypt_flag);
2103 update_session |= smbXsrv_set_crypto_flag(
2104 &session->global->signing_flags, sign_flag);
2106 if (tcon) {
2107 update_tcon |= smbXsrv_set_crypto_flag(
2108 &tcon->global->encryption_flags, encrypt_flag);
2109 update_tcon |= smbXsrv_set_crypto_flag(
2110 &tcon->global->signing_flags, sign_flag);
2113 *update_session_globalp = update_session;
2114 *update_tcon_globalp = update_tcon;
2115 return;
2118 bool smbXsrv_is_signed(uint8_t signing_flags)
2121 * Signing is always enabled, so unless we got an unsigned
2122 * packet and at least one signed packet that was not
2123 * encrypted, the session or tcon is "signed".
2125 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2126 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2129 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2131 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2132 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2135 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2136 struct smbd_smb2_request *req,
2137 bool modify_call)
2139 struct smbXsrv_connection *xconn = req->xconn;
2140 const uint8_t *inhdr;
2141 uint16_t channel_sequence;
2142 uint32_t flags;
2143 int cmp;
2144 struct smbXsrv_open *op;
2145 bool update_open = false;
2146 NTSTATUS status = NT_STATUS_OK;
2148 req->request_counters_updated = false;
2150 if (xconn->protocol < PROTOCOL_SMB2_22) {
2151 return NT_STATUS_OK;
2154 if (req->compat_chain_fsp == NULL) {
2155 return NT_STATUS_OK;
2158 op = req->compat_chain_fsp->op;
2159 if (op == NULL) {
2160 return NT_STATUS_OK;
2163 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2164 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2165 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2167 cmp = channel_sequence - op->global->channel_sequence;
2169 if (abs(cmp) > INT16_MAX) {
2171 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2173 * If the channel sequence number of the request and the one
2174 * known to the server are not equal, the channel sequence
2175 * number and outstanding request counts are only updated
2176 * "... if the unsigned difference using 16-bit arithmetic
2177 * between ChannelSequence and Open.ChannelSequence is less than
2178 * or equal to 0x7FFF ...".
2179 * Otherwise, an error is returned for the modifying
2180 * calls write, set_info, and ioctl.
2182 * There are currently two issues with the description:
2184 * * For the other calls, the document seems to imply
2185 * that processing continues without adapting the
2186 * counters (if the sequence numbers are not equal).
2188 * TODO: This needs clarification!
2190 * * Also, the behaviour if the difference is larger
2191 * than 0x7FFF is not clear. The document seems to
2192 * imply that if such a difference is reached,
2193 * the server starts to ignore the counters or
2194 * in the case of the modifying calls, return errors.
2196 * TODO: This needs clarification!
2198 * At this point Samba tries to be a little more
2199 * clever than the description in the MS-SMB2 document
2200 * by heuristically detecting and properly treating
2201 * a 16 bit overflow of the client-submitted sequence
2202 * number:
2204 * If the stored channel squence number is more than
2205 * 0x7FFF larger than the one from the request, then
2206 * the client-provided sequence number has likely
2207 * overflown. We treat this case as valid instead
2208 * of as failure.
2210 * The MS-SMB2 behaviour would be setting cmp = -1.
2212 cmp *= -1;
2215 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2216 if (cmp == 0) {
2217 op->request_count += 1;
2218 req->request_counters_updated = true;
2219 } else if (cmp > 0) {
2220 op->pre_request_count += op->request_count;
2221 op->request_count = 1;
2222 op->global->channel_sequence = channel_sequence;
2223 update_open = true;
2224 req->request_counters_updated = true;
2225 } else if (modify_call) {
2226 return NT_STATUS_FILE_NOT_AVAILABLE;
2228 } else {
2229 if (cmp == 0 && op->pre_request_count == 0) {
2230 op->request_count += 1;
2231 req->request_counters_updated = true;
2232 } else if (cmp > 0 && op->pre_request_count == 0) {
2233 op->pre_request_count += op->request_count;
2234 op->request_count = 1;
2235 op->global->channel_sequence = channel_sequence;
2236 update_open = true;
2237 req->request_counters_updated = true;
2238 } else if (modify_call) {
2239 return NT_STATUS_FILE_NOT_AVAILABLE;
2243 if (update_open) {
2244 status = smbXsrv_open_update(op);
2247 return status;
2250 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2252 struct smbXsrv_connection *xconn = req->xconn;
2253 const struct smbd_smb2_dispatch_table *call = NULL;
2254 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2255 const uint8_t *inhdr;
2256 uint16_t opcode;
2257 uint32_t flags;
2258 uint64_t mid;
2259 NTSTATUS status;
2260 NTSTATUS session_status;
2261 uint32_t allowed_flags;
2262 NTSTATUS return_value;
2263 struct smbXsrv_session *x = NULL;
2264 bool signing_required = false;
2265 bool encryption_desired = false;
2266 bool encryption_required = false;
2268 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2270 DO_PROFILE_INC(request);
2272 /* TODO: verify more things */
2274 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2275 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2276 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2277 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2278 smb2_opcode_name(opcode),
2279 (unsigned long long)mid));
2281 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2283 * once the protocol is negotiated
2284 * SMB2_OP_NEGPROT is not allowed anymore
2286 if (opcode == SMB2_OP_NEGPROT) {
2287 /* drop the connection */
2288 return NT_STATUS_INVALID_PARAMETER;
2290 } else {
2292 * if the protocol is not negotiated yet
2293 * only SMB2_OP_NEGPROT is allowed.
2295 if (opcode != SMB2_OP_NEGPROT) {
2296 /* drop the connection */
2297 return NT_STATUS_INVALID_PARAMETER;
2302 * Check if the client provided a valid session id,
2303 * if so smbd_smb2_request_check_session() calls
2304 * set_current_user_info().
2306 * As some command don't require a valid session id
2307 * we defer the check of the session_status
2309 session_status = smbd_smb2_request_check_session(req);
2310 x = req->session;
2311 if (x != NULL) {
2312 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2313 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2314 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2317 req->async_internal = false;
2318 req->do_signing = false;
2319 req->do_encryption = false;
2320 req->was_encrypted = false;
2321 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2322 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2323 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2325 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2326 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2327 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2328 (unsigned long long)x->global->session_wire_id,
2329 (unsigned long long)tf_session_id));
2331 * TODO: windows allows this...
2332 * should we drop the connection?
2334 * For now we just return ACCESS_DENIED
2335 * (Windows clients never trigger this)
2336 * and wait for an update of [MS-SMB2].
2338 return smbd_smb2_request_error(req,
2339 NT_STATUS_ACCESS_DENIED);
2342 req->was_encrypted = true;
2345 if (encryption_required && !req->was_encrypted) {
2346 return smbd_smb2_request_error(req,
2347 NT_STATUS_ACCESS_DENIED);
2350 call = smbd_smb2_call(opcode);
2351 if (call == NULL) {
2352 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2355 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2356 SMB2_HDR_FLAG_SIGNED |
2357 SMB2_HDR_FLAG_DFS;
2358 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2359 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2361 if (opcode == SMB2_OP_NEGPROT) {
2362 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2363 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2366 if (opcode == SMB2_OP_CANCEL) {
2367 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2369 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2370 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2372 if ((flags & ~allowed_flags) != 0) {
2373 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2376 if (flags & SMB2_HDR_FLAG_CHAINED) {
2378 * This check is mostly for giving the correct error code
2379 * for compounded requests.
2381 if (!NT_STATUS_IS_OK(session_status)) {
2382 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2384 } else {
2385 req->compat_chain_fsp = NULL;
2388 if (req->was_encrypted) {
2389 signing_required = false;
2390 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2391 DATA_BLOB signing_key = data_blob_null;
2393 if (x == NULL) {
2395 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2396 * If the SMB2 header of the SMB2 NEGOTIATE
2397 * request has the SMB2_FLAGS_SIGNED bit set in the
2398 * Flags field, the server MUST fail the request
2399 * with STATUS_INVALID_PARAMETER.
2401 * Microsoft test tool checks this.
2404 if ((opcode == SMB2_OP_NEGPROT) &&
2405 (flags & SMB2_HDR_FLAG_SIGNED)) {
2406 status = NT_STATUS_INVALID_PARAMETER;
2407 } else {
2408 status = NT_STATUS_USER_SESSION_DELETED;
2410 return smbd_smb2_request_error(req, status);
2413 signing_key = smbd_smb2_signing_key(x, xconn);
2416 * If we have a signing key, we should
2417 * sign the response
2419 if (signing_key.length > 0) {
2420 req->do_signing = true;
2423 status = smb2_signing_check_pdu(signing_key,
2424 xconn->protocol,
2425 SMBD_SMB2_IN_HDR_IOV(req),
2426 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2427 if (!NT_STATUS_IS_OK(status)) {
2428 return smbd_smb2_request_error(req, status);
2432 * Now that we know the request was correctly signed
2433 * we have to sign the response too.
2435 req->do_signing = true;
2437 if (!NT_STATUS_IS_OK(session_status)) {
2438 return smbd_smb2_request_error(req, session_status);
2440 } else if (opcode == SMB2_OP_CANCEL) {
2441 /* Cancel requests are allowed to skip the signing */
2442 } else if (signing_required) {
2444 * If signing is required we try to sign
2445 * a possible error response
2447 req->do_signing = true;
2448 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2451 if (flags & SMB2_HDR_FLAG_CHAINED) {
2452 req->compound_related = true;
2455 if (call->need_session) {
2456 if (!NT_STATUS_IS_OK(session_status)) {
2457 return smbd_smb2_request_error(req, session_status);
2461 if (call->need_tcon) {
2462 SMB_ASSERT(call->need_session);
2465 * This call needs to be run as user.
2467 * smbd_smb2_request_check_tcon()
2468 * calls change_to_user() on success.
2470 status = smbd_smb2_request_check_tcon(req);
2471 if (!NT_STATUS_IS_OK(status)) {
2472 return smbd_smb2_request_error(req, status);
2474 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2475 encryption_desired = true;
2477 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2478 encryption_required = true;
2480 if (encryption_required && !req->was_encrypted) {
2481 return smbd_smb2_request_error(req,
2482 NT_STATUS_ACCESS_DENIED);
2486 if (req->was_encrypted || encryption_desired) {
2487 req->do_encryption = true;
2490 if (req->session) {
2491 bool update_session_global = false;
2492 bool update_tcon_global = false;
2494 smb2srv_update_crypto_flags(req, opcode,
2495 &update_session_global,
2496 &update_tcon_global);
2498 if (update_session_global) {
2499 status = smbXsrv_session_update(x);
2500 if (!NT_STATUS_IS_OK(status)) {
2501 return smbd_smb2_request_error(req, status);
2504 if (update_tcon_global) {
2505 status = smbXsrv_tcon_update(req->tcon);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 return smbd_smb2_request_error(req, status);
2512 if (call->fileid_ofs != 0) {
2513 size_t needed = call->fileid_ofs + 16;
2514 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2515 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2516 uint64_t file_id_persistent;
2517 uint64_t file_id_volatile;
2518 struct files_struct *fsp;
2520 SMB_ASSERT(call->need_tcon);
2522 if (needed > body_size) {
2523 return smbd_smb2_request_error(req,
2524 NT_STATUS_INVALID_PARAMETER);
2527 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2528 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2530 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2531 if (fsp == NULL) {
2532 if (!call->allow_invalid_fileid) {
2533 return smbd_smb2_request_error(req,
2534 NT_STATUS_FILE_CLOSED);
2537 if (file_id_persistent != UINT64_MAX) {
2538 return smbd_smb2_request_error(req,
2539 NT_STATUS_FILE_CLOSED);
2541 if (file_id_volatile != UINT64_MAX) {
2542 return smbd_smb2_request_error(req,
2543 NT_STATUS_FILE_CLOSED);
2548 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 return smbd_smb2_request_error(req, status);
2553 if (call->as_root) {
2554 SMB_ASSERT(call->fileid_ofs == 0);
2555 /* This call needs to be run as root */
2556 change_to_root_user();
2557 } else {
2558 SMB_ASSERT(call->need_tcon);
2561 #define _INBYTES(_r) \
2562 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2564 switch (opcode) {
2565 case SMB2_OP_NEGPROT:
2566 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2567 req->profile, _INBYTES(req));
2568 return_value = smbd_smb2_request_process_negprot(req);
2569 break;
2571 case SMB2_OP_SESSSETUP:
2572 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2573 req->profile, _INBYTES(req));
2574 return_value = smbd_smb2_request_process_sesssetup(req);
2575 break;
2577 case SMB2_OP_LOGOFF:
2578 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2579 req->profile, _INBYTES(req));
2580 return_value = smbd_smb2_request_process_logoff(req);
2581 break;
2583 case SMB2_OP_TCON:
2584 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2585 req->profile, _INBYTES(req));
2586 return_value = smbd_smb2_request_process_tcon(req);
2587 break;
2589 case SMB2_OP_TDIS:
2590 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2591 req->profile, _INBYTES(req));
2592 return_value = smbd_smb2_request_process_tdis(req);
2593 break;
2595 case SMB2_OP_CREATE:
2596 if (req->subreq == NULL) {
2597 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2598 req->profile, _INBYTES(req));
2599 } else {
2600 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2602 return_value = smbd_smb2_request_process_create(req);
2603 break;
2605 case SMB2_OP_CLOSE:
2606 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2607 req->profile, _INBYTES(req));
2608 return_value = smbd_smb2_request_process_close(req);
2609 break;
2611 case SMB2_OP_FLUSH:
2612 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2613 req->profile, _INBYTES(req));
2614 return_value = smbd_smb2_request_process_flush(req);
2615 break;
2617 case SMB2_OP_READ:
2618 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2619 req->profile, _INBYTES(req));
2620 return_value = smbd_smb2_request_process_read(req);
2621 break;
2623 case SMB2_OP_WRITE:
2624 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2625 req->profile, _INBYTES(req));
2626 return_value = smbd_smb2_request_process_write(req);
2627 break;
2629 case SMB2_OP_LOCK:
2630 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2631 req->profile, _INBYTES(req));
2632 return_value = smbd_smb2_request_process_lock(req);
2633 break;
2635 case SMB2_OP_IOCTL:
2636 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2637 req->profile, _INBYTES(req));
2638 return_value = smbd_smb2_request_process_ioctl(req);
2639 break;
2641 case SMB2_OP_CANCEL:
2642 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2643 req->profile, _INBYTES(req));
2644 return_value = smbd_smb2_request_process_cancel(req);
2645 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2648 * We don't need the request anymore cancel requests never
2649 * have a response.
2651 * smbd_smb2_request_process_cancel() already called
2652 * DLIST_REMOVE(xconn->smb2.requests, req);
2654 TALLOC_FREE(req);
2656 break;
2658 case SMB2_OP_KEEPALIVE:
2659 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2660 req->profile, _INBYTES(req));
2661 return_value = smbd_smb2_request_process_keepalive(req);
2662 break;
2664 case SMB2_OP_QUERY_DIRECTORY:
2665 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2666 req->profile, _INBYTES(req));
2667 return_value = smbd_smb2_request_process_query_directory(req);
2668 break;
2670 case SMB2_OP_NOTIFY:
2671 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2672 req->profile, _INBYTES(req));
2673 return_value = smbd_smb2_request_process_notify(req);
2674 break;
2676 case SMB2_OP_GETINFO:
2677 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2678 req->profile, _INBYTES(req));
2679 return_value = smbd_smb2_request_process_getinfo(req);
2680 break;
2682 case SMB2_OP_SETINFO:
2683 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2684 req->profile, _INBYTES(req));
2685 return_value = smbd_smb2_request_process_setinfo(req);
2686 break;
2688 case SMB2_OP_BREAK:
2689 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2690 req->profile, _INBYTES(req));
2691 return_value = smbd_smb2_request_process_break(req);
2692 break;
2694 default:
2695 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2696 break;
2698 return return_value;
2701 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2703 struct smbXsrv_connection *xconn = req->xconn;
2704 const uint8_t *inhdr;
2705 uint16_t channel_sequence;
2706 struct smbXsrv_open *op;
2708 if (!req->request_counters_updated) {
2709 return;
2712 if (xconn->protocol < PROTOCOL_SMB2_22) {
2713 return;
2716 if (req->compat_chain_fsp == NULL) {
2717 return;
2720 op = req->compat_chain_fsp->op;
2721 if (op == NULL) {
2722 return;
2725 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2726 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2728 if (op->global->channel_sequence == channel_sequence) {
2729 SMB_ASSERT(op->request_count > 0);
2730 op->request_count -= 1;
2731 } else {
2732 SMB_ASSERT(op->pre_request_count > 0);
2733 op->pre_request_count -= 1;
2737 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2739 struct smbXsrv_connection *xconn = req->xconn;
2740 int first_idx = 1;
2741 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2742 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2743 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2744 NTSTATUS status;
2745 bool ok;
2747 req->subreq = NULL;
2748 TALLOC_FREE(req->async_te);
2750 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2751 smbd_smb2_request_reply_update_counts(req);
2753 if (req->do_encryption &&
2754 (firsttf->iov_len == 0) &&
2755 (req->first_key.length == 0) &&
2756 (req->session != NULL) &&
2757 (req->session->global->encryption_key.length != 0))
2759 DATA_BLOB encryption_key = req->session->global->encryption_key;
2760 uint8_t *tf;
2761 uint64_t session_id = req->session->global->session_wire_id;
2762 uint64_t nonce_high;
2763 uint64_t nonce_low;
2765 status = smb2_get_new_nonce(req->session,
2766 &nonce_high,
2767 &nonce_low);
2768 if (!NT_STATUS_IS_OK(status)) {
2769 return status;
2773 * We need to place the SMB2_TRANSFORM header before the
2774 * first SMB2 header
2778 * we need to remember the encryption key
2779 * and defer the signing/encryption until
2780 * we are sure that we do not change
2781 * the header again.
2783 req->first_key = data_blob_dup_talloc(req, encryption_key);
2784 if (req->first_key.data == NULL) {
2785 return NT_STATUS_NO_MEMORY;
2788 tf = talloc_zero_array(req, uint8_t,
2789 SMB2_TF_HDR_SIZE);
2790 if (tf == NULL) {
2791 return NT_STATUS_NO_MEMORY;
2794 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2795 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2796 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2797 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2799 firsttf->iov_base = (void *)tf;
2800 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2803 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2804 (req->last_key.length > 0) &&
2805 (firsttf->iov_len == 0))
2807 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2808 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2811 * As we are sure the header of the last request in the
2812 * compound chain will not change, we can to sign here
2813 * with the last signing key we remembered.
2815 status = smb2_signing_sign_pdu(req->last_key,
2816 xconn->protocol,
2817 lasthdr,
2818 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2819 if (!NT_STATUS_IS_OK(status)) {
2820 return status;
2823 if (req->last_key.length > 0) {
2824 data_blob_clear_free(&req->last_key);
2827 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2828 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2830 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2832 if (req->current_idx < req->out.vector_count) {
2834 * We must process the remaining compound
2835 * SMB2 requests before any new incoming SMB2
2836 * requests. This is because incoming SMB2
2837 * requests may include a cancel for a
2838 * compound request we haven't processed
2839 * yet.
2841 struct tevent_immediate *im = tevent_create_immediate(req);
2842 if (!im) {
2843 return NT_STATUS_NO_MEMORY;
2846 if (req->do_signing && firsttf->iov_len == 0) {
2847 struct smbXsrv_session *x = req->session;
2848 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2851 * we need to remember the signing key
2852 * and defer the signing until
2853 * we are sure that we do not change
2854 * the header again.
2856 req->last_key = data_blob_dup_talloc(req, signing_key);
2857 if (req->last_key.data == NULL) {
2858 return NT_STATUS_NO_MEMORY;
2862 tevent_schedule_immediate(im,
2863 req->sconn->ev_ctx,
2864 smbd_smb2_request_dispatch_immediate,
2865 req);
2866 return NT_STATUS_OK;
2869 if (req->compound_related) {
2870 req->compound_related = false;
2873 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2874 if (!ok) {
2875 return NT_STATUS_INVALID_PARAMETER_MIX;
2878 /* Set credit for these operations (zero credits if this
2879 is a final reply for an async operation). */
2880 smb2_calculate_credits(req, req);
2883 * now check if we need to sign the current response
2885 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2886 status = smb2_signing_encrypt_pdu(req->first_key,
2887 xconn->smb2.server.cipher,
2888 firsttf,
2889 req->out.vector_count - first_idx);
2890 if (!NT_STATUS_IS_OK(status)) {
2891 return status;
2893 } else if (req->do_signing) {
2894 struct smbXsrv_session *x = req->session;
2895 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2897 status = smb2_signing_sign_pdu(signing_key,
2898 xconn->protocol,
2899 outhdr,
2900 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2901 if (!NT_STATUS_IS_OK(status)) {
2902 return status;
2905 if (req->first_key.length > 0) {
2906 data_blob_clear_free(&req->first_key);
2909 if (req->preauth != NULL) {
2910 struct hc_sha512state sctx;
2911 int i;
2913 samba_SHA512_Init(&sctx);
2914 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2915 sizeof(req->preauth->sha512_value));
2916 for (i = 1; i < req->in.vector_count; i++) {
2917 samba_SHA512_Update(&sctx,
2918 req->in.vector[i].iov_base,
2919 req->in.vector[i].iov_len);
2921 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2923 samba_SHA512_Init(&sctx);
2924 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2925 sizeof(req->preauth->sha512_value));
2926 for (i = 1; i < req->out.vector_count; i++) {
2927 samba_SHA512_Update(&sctx,
2928 req->out.vector[i].iov_base,
2929 req->out.vector[i].iov_len);
2931 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2933 req->preauth = NULL;
2936 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2937 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2938 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2939 /* Dynamic part is NULL. Chop it off,
2940 We're going to send it via sendfile. */
2941 req->out.vector_count -= 1;
2945 * We're done with this request -
2946 * move it off the "being processed" queue.
2948 DLIST_REMOVE(xconn->smb2.requests, req);
2950 req->queue_entry.mem_ctx = req;
2951 req->queue_entry.vector = req->out.vector;
2952 req->queue_entry.count = req->out.vector_count;
2953 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2954 xconn->smb2.send_queue_len++;
2956 status = smbd_smb2_flush_send_queue(xconn);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 return status;
2961 return NT_STATUS_OK;
2964 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2966 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2967 struct tevent_immediate *im,
2968 void *private_data)
2970 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2971 struct smbd_smb2_request);
2972 struct smbXsrv_connection *xconn = req->xconn;
2973 NTSTATUS status;
2975 TALLOC_FREE(im);
2977 if (DEBUGLEVEL >= 10) {
2978 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2979 req->current_idx, req->in.vector_count));
2980 print_req_vectors(req);
2983 status = smbd_smb2_request_dispatch(req);
2984 if (!NT_STATUS_IS_OK(status)) {
2985 smbd_server_connection_terminate(xconn, nt_errstr(status));
2986 return;
2989 status = smbd_smb2_request_next_incoming(xconn);
2990 if (!NT_STATUS_IS_OK(status)) {
2991 smbd_server_connection_terminate(xconn, nt_errstr(status));
2992 return;
2996 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2997 NTSTATUS status,
2998 DATA_BLOB body, DATA_BLOB *dyn,
2999 const char *location)
3001 uint8_t *outhdr;
3002 struct iovec *outbody_v;
3003 struct iovec *outdyn_v;
3004 uint32_t next_command_ofs;
3006 DEBUG(10,("smbd_smb2_request_done_ex: "
3007 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3008 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3009 dyn ? "yes": "no",
3010 (unsigned int)(dyn ? dyn->length : 0),
3011 location));
3013 if (body.length < 2) {
3014 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3017 if ((body.length % 2) != 0) {
3018 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3021 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3022 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3023 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3025 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3026 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3028 outbody_v->iov_base = (void *)body.data;
3029 outbody_v->iov_len = body.length;
3031 if (dyn) {
3032 outdyn_v->iov_base = (void *)dyn->data;
3033 outdyn_v->iov_len = dyn->length;
3034 } else {
3035 outdyn_v->iov_base = NULL;
3036 outdyn_v->iov_len = 0;
3040 * See if we need to recalculate the offset to the next response
3042 * Note that all responses may require padding (including the very last
3043 * one).
3045 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3046 next_command_ofs = SMB2_HDR_BODY;
3047 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3048 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3051 if ((next_command_ofs % 8) != 0) {
3052 size_t pad_size = 8 - (next_command_ofs % 8);
3053 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3055 * if the dyn buffer is empty
3056 * we can use it to add padding
3058 uint8_t *pad;
3060 pad = talloc_zero_array(req,
3061 uint8_t, pad_size);
3062 if (pad == NULL) {
3063 return smbd_smb2_request_error(req,
3064 NT_STATUS_NO_MEMORY);
3067 outdyn_v->iov_base = (void *)pad;
3068 outdyn_v->iov_len = pad_size;
3069 } else {
3071 * For now we copy the dynamic buffer
3072 * and add the padding to the new buffer
3074 size_t old_size;
3075 uint8_t *old_dyn;
3076 size_t new_size;
3077 uint8_t *new_dyn;
3079 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3080 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3082 new_size = old_size + pad_size;
3083 new_dyn = talloc_zero_array(req,
3084 uint8_t, new_size);
3085 if (new_dyn == NULL) {
3086 return smbd_smb2_request_error(req,
3087 NT_STATUS_NO_MEMORY);
3090 memcpy(new_dyn, old_dyn, old_size);
3091 memset(new_dyn + old_size, 0, pad_size);
3093 outdyn_v->iov_base = (void *)new_dyn;
3094 outdyn_v->iov_len = new_size;
3096 next_command_ofs += pad_size;
3099 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3100 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3101 } else {
3102 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3104 return smbd_smb2_request_reply(req);
3107 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3108 NTSTATUS status,
3109 DATA_BLOB *info,
3110 const char *location)
3112 struct smbXsrv_connection *xconn = req->xconn;
3113 DATA_BLOB body;
3114 DATA_BLOB _dyn;
3115 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3116 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3118 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3119 "at %s\n", req->current_idx, nt_errstr(status),
3120 info ? " +info" : "", location);
3122 if (unread_bytes) {
3123 /* Recvfile error. Drain incoming socket. */
3124 size_t ret;
3126 errno = 0;
3127 ret = drain_socket(xconn->transport.sock, unread_bytes);
3128 if (ret != unread_bytes) {
3129 NTSTATUS error;
3131 if (errno == 0) {
3132 error = NT_STATUS_IO_DEVICE_ERROR;
3133 } else {
3134 error = map_nt_error_from_unix_common(errno);
3137 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3138 "ret[%u] errno[%d] => %s\n",
3139 (unsigned)unread_bytes,
3140 (unsigned)ret, errno, nt_errstr(error)));
3141 return error;
3145 body.data = outhdr + SMB2_HDR_BODY;
3146 body.length = 8;
3147 SSVAL(body.data, 0, 9);
3149 if (info) {
3150 SIVAL(body.data, 0x04, info->length);
3151 } else {
3152 /* Allocated size of req->out.vector[i].iov_base
3153 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3154 * 1 byte without having to do an alloc.
3156 info = &_dyn;
3157 info->data = ((uint8_t *)outhdr) +
3158 OUTVEC_ALLOC_SIZE - 1;
3159 info->length = 1;
3160 SCVAL(info->data, 0, 0);
3164 * Note: Even if there is an error, continue to process the request.
3165 * per MS-SMB2.
3168 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3172 struct smbd_smb2_send_break_state {
3173 struct smbd_smb2_send_queue queue_entry;
3174 uint8_t nbt_hdr[NBT_HDR_SIZE];
3175 uint8_t tf[SMB2_TF_HDR_SIZE];
3176 uint8_t hdr[SMB2_HDR_BODY];
3177 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3178 uint8_t body[1];
3181 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3182 struct smbXsrv_session *session,
3183 struct smbXsrv_tcon *tcon,
3184 const uint8_t *body,
3185 size_t body_len)
3187 struct smbd_smb2_send_break_state *state;
3188 bool do_encryption = false;
3189 uint64_t session_wire_id = 0;
3190 uint64_t nonce_high = 0;
3191 uint64_t nonce_low = 0;
3192 NTSTATUS status;
3193 size_t statelen;
3194 bool ok;
3196 if (session != NULL) {
3197 session_wire_id = session->global->session_wire_id;
3198 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3199 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3200 do_encryption = true;
3204 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3205 body_len;
3207 state = talloc_zero_size(xconn, statelen);
3208 if (state == NULL) {
3209 return NT_STATUS_NO_MEMORY;
3211 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3213 if (do_encryption) {
3214 status = smb2_get_new_nonce(session,
3215 &nonce_high,
3216 &nonce_low);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 return status;
3222 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3223 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3224 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3225 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3227 SIVAL(state->hdr, 0, SMB2_MAGIC);
3228 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3229 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3230 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3231 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3232 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3233 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3234 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3235 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3236 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3237 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3238 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3239 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3241 state->vector[0] = (struct iovec) {
3242 .iov_base = state->nbt_hdr,
3243 .iov_len = sizeof(state->nbt_hdr)
3246 if (do_encryption) {
3247 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3248 .iov_base = state->tf,
3249 .iov_len = sizeof(state->tf)
3251 } else {
3252 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3253 .iov_base = NULL,
3254 .iov_len = 0
3258 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3259 .iov_base = state->hdr,
3260 .iov_len = sizeof(state->hdr)
3263 memcpy(state->body, body, body_len);
3265 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3266 .iov_base = state->body,
3267 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3271 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3274 ok = smb2_setup_nbt_length(state->vector,
3275 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3276 if (!ok) {
3277 return NT_STATUS_INVALID_PARAMETER_MIX;
3280 if (do_encryption) {
3281 DATA_BLOB encryption_key = session->global->encryption_key;
3283 status = smb2_signing_encrypt_pdu(encryption_key,
3284 xconn->smb2.server.cipher,
3285 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3286 SMBD_SMB2_NUM_IOV_PER_REQ);
3287 if (!NT_STATUS_IS_OK(status)) {
3288 return status;
3292 state->queue_entry.mem_ctx = state;
3293 state->queue_entry.vector = state->vector;
3294 state->queue_entry.count = ARRAY_SIZE(state->vector);
3295 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3296 xconn->smb2.send_queue_len++;
3298 status = smbd_smb2_flush_send_queue(xconn);
3299 if (!NT_STATUS_IS_OK(status)) {
3300 return status;
3303 return NT_STATUS_OK;
3306 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3307 struct smbXsrv_session *session,
3308 struct smbXsrv_tcon *tcon,
3309 struct smbXsrv_open *op,
3310 uint8_t oplock_level)
3312 uint8_t body[0x18];
3314 SSVAL(body, 0x00, sizeof(body));
3315 SCVAL(body, 0x02, oplock_level);
3316 SCVAL(body, 0x03, 0); /* reserved */
3317 SIVAL(body, 0x04, 0); /* reserved */
3318 SBVAL(body, 0x08, op->global->open_persistent_id);
3319 SBVAL(body, 0x10, op->global->open_volatile_id);
3321 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3324 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3325 uint16_t new_epoch,
3326 uint32_t lease_flags,
3327 struct smb2_lease_key *lease_key,
3328 uint32_t current_lease_state,
3329 uint32_t new_lease_state)
3331 uint8_t body[0x2c];
3333 SSVAL(body, 0x00, sizeof(body));
3334 SSVAL(body, 0x02, new_epoch);
3335 SIVAL(body, 0x04, lease_flags);
3336 SBVAL(body, 0x08, lease_key->data[0]);
3337 SBVAL(body, 0x10, lease_key->data[1]);
3338 SIVAL(body, 0x18, current_lease_state);
3339 SIVAL(body, 0x1c, new_lease_state);
3340 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3341 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3342 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3344 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3347 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3349 NTSTATUS status;
3350 uint32_t flags;
3351 uint64_t file_id_persistent;
3352 uint64_t file_id_volatile;
3353 struct smbXsrv_open *op = NULL;
3354 struct files_struct *fsp = NULL;
3355 const uint8_t *body = NULL;
3358 * This is only called with a pktbuf
3359 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3360 * bytes
3363 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3364 /* Transform header. Cannot recvfile. */
3365 return false;
3367 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3368 /* Not SMB2. Normal error path will cope. */
3369 return false;
3371 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3372 /* Not SMB2. Normal error path will cope. */
3373 return false;
3375 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3376 /* Needs to be a WRITE. */
3377 return false;
3379 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3380 /* Chained. Cannot recvfile. */
3381 return false;
3383 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3384 if (flags & SMB2_HDR_FLAG_CHAINED) {
3385 /* Chained. Cannot recvfile. */
3386 return false;
3388 if (flags & SMB2_HDR_FLAG_SIGNED) {
3389 /* Signed. Cannot recvfile. */
3390 return false;
3393 body = &state->pktbuf[SMB2_HDR_BODY];
3395 file_id_persistent = BVAL(body, 0x10);
3396 file_id_volatile = BVAL(body, 0x18);
3398 status = smb2srv_open_lookup(state->req->xconn,
3399 file_id_persistent,
3400 file_id_volatile,
3401 0, /* now */
3402 &op);
3403 if (!NT_STATUS_IS_OK(status)) {
3404 return false;
3407 fsp = op->compat;
3408 if (fsp == NULL) {
3409 return false;
3411 if (fsp->conn == NULL) {
3412 return false;
3415 if (IS_IPC(fsp->conn)) {
3416 return false;
3418 if (IS_PRINT(fsp->conn)) {
3419 return false;
3422 DEBUG(10,("Doing recvfile write len = %u\n",
3423 (unsigned int)(state->pktfull - state->pktlen)));
3425 return true;
3428 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3430 struct smbd_server_connection *sconn = xconn->client->sconn;
3431 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3432 size_t max_send_queue_len;
3433 size_t cur_send_queue_len;
3435 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3437 * we're not supposed to do any io
3439 return NT_STATUS_OK;
3442 if (state->req != NULL) {
3444 * if there is already a tstream_readv_pdu
3445 * pending, we are done.
3447 return NT_STATUS_OK;
3450 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3451 cur_send_queue_len = xconn->smb2.send_queue_len;
3453 if (cur_send_queue_len > max_send_queue_len) {
3455 * if we have a lot of requests to send,
3456 * we wait until they are on the wire until we
3457 * ask for the next request.
3459 return NT_STATUS_OK;
3462 /* ask for the next request */
3463 ZERO_STRUCTP(state);
3464 state->req = smbd_smb2_request_allocate(xconn);
3465 if (state->req == NULL) {
3466 return NT_STATUS_NO_MEMORY;
3468 state->req->sconn = sconn;
3469 state->req->xconn = xconn;
3470 state->min_recv_size = lp_min_receive_file_size();
3472 TEVENT_FD_READABLE(xconn->transport.fde);
3474 return NT_STATUS_OK;
3477 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3478 uint64_t expected_seq_low,
3479 const uint8_t *inpdu, size_t size)
3481 struct smbd_server_connection *sconn = xconn->client->sconn;
3482 NTSTATUS status;
3483 struct smbd_smb2_request *req = NULL;
3485 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3486 (unsigned int)size));
3488 status = smbd_initialize_smb2(xconn, expected_seq_low);
3489 if (!NT_STATUS_IS_OK(status)) {
3490 smbd_server_connection_terminate(xconn, nt_errstr(status));
3491 return;
3494 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3495 if (!NT_STATUS_IS_OK(status)) {
3496 smbd_server_connection_terminate(xconn, nt_errstr(status));
3497 return;
3500 status = smbd_smb2_request_validate(req);
3501 if (!NT_STATUS_IS_OK(status)) {
3502 smbd_server_connection_terminate(xconn, nt_errstr(status));
3503 return;
3506 status = smbd_smb2_request_setup_out(req);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 smbd_server_connection_terminate(xconn, nt_errstr(status));
3509 return;
3512 #ifdef WITH_PROFILE
3514 * this was already counted at the SMB1 layer =>
3515 * smbd_smb2_request_dispatch() should not count it twice.
3517 if (profile_p->values.request_stats.count > 0) {
3518 profile_p->values.request_stats.count--;
3520 #endif
3521 status = smbd_smb2_request_dispatch(req);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 smbd_server_connection_terminate(xconn, nt_errstr(status));
3524 return;
3527 status = smbd_smb2_request_next_incoming(xconn);
3528 if (!NT_STATUS_IS_OK(status)) {
3529 smbd_server_connection_terminate(xconn, nt_errstr(status));
3530 return;
3533 sconn->num_requests++;
3536 static int socket_error_from_errno(int ret,
3537 int sys_errno,
3538 bool *retry)
3540 *retry = false;
3542 if (ret >= 0) {
3543 return 0;
3546 if (ret != -1) {
3547 return EIO;
3550 if (sys_errno == 0) {
3551 return EIO;
3554 if (sys_errno == EINTR) {
3555 *retry = true;
3556 return sys_errno;
3559 if (sys_errno == EINPROGRESS) {
3560 *retry = true;
3561 return sys_errno;
3564 if (sys_errno == EAGAIN) {
3565 *retry = true;
3566 return sys_errno;
3569 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3570 if (sys_errno == ENOMEM) {
3571 *retry = true;
3572 return sys_errno;
3575 #ifdef EWOULDBLOCK
3576 #if EWOULDBLOCK != EAGAIN
3577 if (sys_errno == EWOULDBLOCK) {
3578 *retry = true;
3579 return sys_errno;
3581 #endif
3582 #endif
3584 return sys_errno;
3587 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3589 int ret;
3590 int err;
3591 bool retry;
3592 NTSTATUS status;
3594 if (xconn->smb2.send_queue == NULL) {
3595 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3596 return NT_STATUS_OK;
3599 while (xconn->smb2.send_queue != NULL) {
3600 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3601 bool ok;
3603 if (e->sendfile_header != NULL) {
3604 size_t size = 0;
3605 size_t i = 0;
3606 uint8_t *buf;
3608 status = NT_STATUS_INTERNAL_ERROR;
3610 for (i=0; i < e->count; i++) {
3611 size += e->vector[i].iov_len;
3614 if (size <= e->sendfile_header->length) {
3615 buf = e->sendfile_header->data;
3616 } else {
3617 buf = talloc_array(e->mem_ctx, uint8_t, size);
3618 if (buf == NULL) {
3619 return NT_STATUS_NO_MEMORY;
3623 size = 0;
3624 for (i=0; i < e->count; i++) {
3625 memcpy(buf+size,
3626 e->vector[i].iov_base,
3627 e->vector[i].iov_len);
3628 size += e->vector[i].iov_len;
3631 e->sendfile_header->data = buf;
3632 e->sendfile_header->length = size;
3633 e->sendfile_status = &status;
3634 e->count = 0;
3636 xconn->smb2.send_queue_len--;
3637 DLIST_REMOVE(xconn->smb2.send_queue, e);
3639 * This triggers the sendfile path via
3640 * the destructor.
3642 talloc_free(e->mem_ctx);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 return status;
3647 continue;
3650 ret = writev(xconn->transport.sock, e->vector, e->count);
3651 if (ret == 0) {
3652 /* propagate end of file */
3653 return NT_STATUS_INTERNAL_ERROR;
3655 err = socket_error_from_errno(ret, errno, &retry);
3656 if (retry) {
3657 /* retry later */
3658 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3659 return NT_STATUS_OK;
3661 if (err != 0) {
3662 return map_nt_error_from_unix_common(err);
3665 ok = iov_advance(&e->vector, &e->count, ret);
3666 if (!ok) {
3667 return NT_STATUS_INTERNAL_ERROR;
3670 if (e->count > 0) {
3671 /* we have more to write */
3672 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3673 return NT_STATUS_OK;
3676 xconn->smb2.send_queue_len--;
3677 DLIST_REMOVE(xconn->smb2.send_queue, e);
3678 talloc_free(e->mem_ctx);
3682 * Restart reads if we were blocked on
3683 * draining the send queue.
3686 status = smbd_smb2_request_next_incoming(xconn);
3687 if (!NT_STATUS_IS_OK(status)) {
3688 return status;
3691 return NT_STATUS_OK;
3694 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3695 uint16_t fde_flags)
3697 struct smbd_server_connection *sconn = xconn->client->sconn;
3698 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3699 struct smbd_smb2_request *req = NULL;
3700 size_t min_recvfile_size = UINT32_MAX;
3701 int ret;
3702 int err;
3703 bool retry;
3704 NTSTATUS status;
3705 NTTIME now;
3707 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3709 * we're not supposed to do any io
3711 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3712 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3713 return NT_STATUS_OK;
3716 if (fde_flags & TEVENT_FD_WRITE) {
3717 status = smbd_smb2_flush_send_queue(xconn);
3718 if (!NT_STATUS_IS_OK(status)) {
3719 return status;
3723 if (!(fde_flags & TEVENT_FD_READ)) {
3724 return NT_STATUS_OK;
3727 if (state->req == NULL) {
3728 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3729 return NT_STATUS_OK;
3732 again:
3733 if (!state->hdr.done) {
3734 state->hdr.done = true;
3736 state->vector.iov_base = (void *)state->hdr.nbt;
3737 state->vector.iov_len = NBT_HDR_SIZE;
3740 ret = readv(xconn->transport.sock, &state->vector, 1);
3741 if (ret == 0) {
3742 /* propagate end of file */
3743 return NT_STATUS_END_OF_FILE;
3745 err = socket_error_from_errno(ret, errno, &retry);
3746 if (retry) {
3747 /* retry later */
3748 TEVENT_FD_READABLE(xconn->transport.fde);
3749 return NT_STATUS_OK;
3751 if (err != 0) {
3752 return map_nt_error_from_unix_common(err);
3755 if (ret < state->vector.iov_len) {
3756 uint8_t *base;
3757 base = (uint8_t *)state->vector.iov_base;
3758 base += ret;
3759 state->vector.iov_base = (void *)base;
3760 state->vector.iov_len -= ret;
3761 /* we have more to read */
3762 TEVENT_FD_READABLE(xconn->transport.fde);
3763 return NT_STATUS_OK;
3766 if (state->pktlen > 0) {
3767 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3769 * Not a possible receivefile write.
3770 * Read the rest of the data.
3772 state->doing_receivefile = false;
3774 state->pktbuf = talloc_realloc(state->req,
3775 state->pktbuf,
3776 uint8_t,
3777 state->pktfull);
3778 if (state->pktbuf == NULL) {
3779 return NT_STATUS_NO_MEMORY;
3782 state->vector.iov_base = (void *)(state->pktbuf +
3783 state->pktlen);
3784 state->vector.iov_len = (state->pktfull -
3785 state->pktlen);
3787 state->pktlen = state->pktfull;
3788 goto again;
3792 * Either this is a receivefile write so we've
3793 * done a short read, or if not we have all the data.
3795 goto got_full;
3799 * Now we analyze the NBT header
3801 if (state->hdr.nbt[0] != 0x00) {
3802 state->min_recv_size = 0;
3804 state->pktfull = smb2_len(state->hdr.nbt);
3805 if (state->pktfull == 0) {
3806 goto got_full;
3809 if (state->min_recv_size != 0) {
3810 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3811 min_recvfile_size += state->min_recv_size;
3814 if (state->pktfull > min_recvfile_size) {
3816 * Might be a receivefile write. Read the SMB2 HEADER +
3817 * SMB2_WRITE header first. Set 'doing_receivefile'
3818 * as we're *attempting* receivefile write. If this
3819 * turns out not to be a SMB2_WRITE request or otherwise
3820 * not suitable then we'll just read the rest of the data
3821 * the next time this function is called.
3823 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3824 state->doing_receivefile = true;
3825 } else {
3826 state->pktlen = state->pktfull;
3829 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3830 if (state->pktbuf == NULL) {
3831 return NT_STATUS_NO_MEMORY;
3834 state->vector.iov_base = (void *)state->pktbuf;
3835 state->vector.iov_len = state->pktlen;
3837 goto again;
3839 got_full:
3841 if (state->hdr.nbt[0] != 0x00) {
3842 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3843 state->hdr.nbt[0]));
3845 req = state->req;
3846 ZERO_STRUCTP(state);
3847 state->req = req;
3848 state->min_recv_size = lp_min_receive_file_size();
3849 req = NULL;
3850 goto again;
3853 req = state->req;
3854 state->req = NULL;
3856 req->request_time = timeval_current();
3857 now = timeval_to_nttime(&req->request_time);
3859 status = smbd_smb2_inbuf_parse_compound(xconn,
3860 now,
3861 state->pktbuf,
3862 state->pktlen,
3863 req,
3864 &req->in.vector,
3865 &req->in.vector_count);
3866 if (!NT_STATUS_IS_OK(status)) {
3867 return status;
3870 if (state->doing_receivefile) {
3871 req->smb1req = talloc_zero(req, struct smb_request);
3872 if (req->smb1req == NULL) {
3873 return NT_STATUS_NO_MEMORY;
3875 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3878 ZERO_STRUCTP(state);
3880 req->current_idx = 1;
3882 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3883 req->current_idx, req->in.vector_count));
3885 status = smbd_smb2_request_validate(req);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 return status;
3890 status = smbd_smb2_request_setup_out(req);
3891 if (!NT_STATUS_IS_OK(status)) {
3892 return status;
3895 status = smbd_smb2_request_dispatch(req);
3896 if (!NT_STATUS_IS_OK(status)) {
3897 return status;
3900 sconn->num_requests++;
3902 /* The timeout_processing function isn't run nearly
3903 often enough to implement 'max log size' without
3904 overrunning the size of the file by many megabytes.
3905 This is especially true if we are running at debug
3906 level 10. Checking every 50 SMB2s is a nice
3907 tradeoff of performance vs log file size overrun. */
3909 if ((sconn->num_requests % 50) == 0 &&
3910 need_to_check_log_size()) {
3911 change_to_root_user();
3912 check_log_size();
3915 status = smbd_smb2_request_next_incoming(xconn);
3916 if (!NT_STATUS_IS_OK(status)) {
3917 return status;
3920 return NT_STATUS_OK;
3923 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3924 struct tevent_fd *fde,
3925 uint16_t flags,
3926 void *private_data)
3928 struct smbXsrv_connection *xconn =
3929 talloc_get_type_abort(private_data,
3930 struct smbXsrv_connection);
3931 NTSTATUS status;
3933 status = smbd_smb2_io_handler(xconn, flags);
3934 if (!NT_STATUS_IS_OK(status)) {
3935 smbd_server_connection_terminate(xconn, nt_errstr(status));
3936 return;