docs: Fix typo in man smb.conf.
[Samba.git] / source3 / smbd / smb2_server.c
blobb0a4afc867504eb1afbb1e43130a4019ee81ac66
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 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
208 uint64_t expected_seq_low)
210 TALLOC_FREE(xconn->transport.fde);
212 xconn->smb2.credits.seq_low = expected_seq_low;
213 xconn->smb2.credits.seq_range = 1;
214 xconn->smb2.credits.granted = 1;
215 xconn->smb2.credits.max = lp_smb2_max_credits();
216 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
217 xconn->smb2.credits.max);
218 if (xconn->smb2.credits.bitmap == NULL) {
219 return NT_STATUS_NO_MEMORY;
222 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
223 xconn,
224 xconn->transport.sock,
225 TEVENT_FD_READ,
226 smbd_smb2_connection_handler,
227 xconn);
228 if (xconn->transport.fde == NULL) {
229 return NT_STATUS_NO_MEMORY;
232 /* Ensure child is set to non-blocking mode */
233 set_blocking(xconn->transport.sock, false);
234 return NT_STATUS_OK;
237 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
238 #define _smb2_setlen(_buf,len) do { \
239 uint8_t *buf = (uint8_t *)_buf; \
240 buf[0] = 0; \
241 buf[1] = ((len)&0xFF0000)>>16; \
242 buf[2] = ((len)&0xFF00)>>8; \
243 buf[3] = (len)&0xFF; \
244 } while (0)
246 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
248 ssize_t len;
250 if (count == 0) {
251 return false;
254 len = iov_buflen(vector+1, count-1);
256 if ((len == -1) || (len > 0xFFFFFF)) {
257 return false;
260 _smb2_setlen(vector[0].iov_base, len);
261 return true;
264 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
266 if (req->first_key.length > 0) {
267 data_blob_clear_free(&req->first_key);
269 if (req->last_key.length > 0) {
270 data_blob_clear_free(&req->last_key);
272 return 0;
275 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
277 TALLOC_CTX *mem_pool;
278 struct smbd_smb2_request *req;
280 #if 0
281 /* Enable this to find subtle valgrind errors. */
282 mem_pool = talloc_init("smbd_smb2_request_allocate");
283 #else
284 mem_pool = talloc_tos();
285 #endif
286 if (mem_pool == NULL) {
287 return NULL;
290 req = talloc_zero(mem_pool, struct smbd_smb2_request);
291 if (req == NULL) {
292 talloc_free(mem_pool);
293 return NULL;
295 talloc_reparent(mem_pool, mem_ctx, req);
296 #if 0
297 TALLOC_FREE(mem_pool);
298 #endif
300 req->last_session_id = UINT64_MAX;
301 req->last_tid = UINT32_MAX;
303 talloc_set_destructor(req, smbd_smb2_request_destructor);
305 return req;
308 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
309 NTTIME now,
310 uint8_t *buf,
311 size_t buflen,
312 struct smbd_smb2_request *req,
313 struct iovec **piov,
314 int *pnum_iov)
316 TALLOC_CTX *mem_ctx = req;
317 struct iovec *iov;
318 int num_iov = 1;
319 size_t taken = 0;
320 uint8_t *first_hdr = buf;
321 size_t verified_buflen = 0;
322 uint8_t *tf = NULL;
323 size_t tf_len = 0;
326 * Note: index '0' is reserved for the transport protocol
328 iov = req->in._vector;
330 while (taken < buflen) {
331 size_t len = buflen - taken;
332 uint8_t *hdr = first_hdr + taken;
333 struct iovec *cur;
334 size_t full_size;
335 size_t next_command_ofs;
336 uint16_t body_size;
337 uint8_t *body = NULL;
338 uint32_t dyn_size;
339 uint8_t *dyn = NULL;
340 struct iovec *iov_alloc = NULL;
342 if (iov != req->in._vector) {
343 iov_alloc = iov;
346 if (verified_buflen > taken) {
347 len = verified_buflen - taken;
348 } else {
349 tf = NULL;
350 tf_len = 0;
353 if (len < 4) {
354 DEBUG(10, ("%d bytes left, expected at least %d\n",
355 (int)len, 4));
356 goto inval;
358 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
359 struct smbXsrv_session *s = NULL;
360 uint64_t uid;
361 struct iovec tf_iov[2];
362 NTSTATUS status;
363 size_t enc_len;
365 if (xconn->protocol < PROTOCOL_SMB2_24) {
366 DEBUG(10, ("Got SMB2_TRANSFORM header, "
367 "but dialect[0x%04X] is used\n",
368 xconn->smb2.server.dialect));
369 goto inval;
372 if (xconn->smb2.server.cipher == 0) {
373 DEBUG(10, ("Got SMB2_TRANSFORM header, "
374 "but not negotiated "
375 "client[0x%08X] server[0x%08X]\n",
376 xconn->smb2.client.capabilities,
377 xconn->smb2.server.capabilities));
378 goto inval;
381 if (len < SMB2_TF_HDR_SIZE) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)len, SMB2_TF_HDR_SIZE));
384 goto inval;
386 tf = hdr;
387 tf_len = SMB2_TF_HDR_SIZE;
388 taken += tf_len;
390 hdr = first_hdr + taken;
391 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
392 uid = BVAL(tf, SMB2_TF_SESSION_ID);
394 if (len < SMB2_TF_HDR_SIZE + enc_len) {
395 DEBUG(1, ("%d bytes left, expected at least %d\n",
396 (int)len,
397 (int)(SMB2_TF_HDR_SIZE + enc_len)));
398 goto inval;
401 status = smb2srv_session_lookup_conn(xconn, uid, now,
402 &s);
403 if (s == NULL) {
404 DEBUG(1, ("invalid session[%llu] in "
405 "SMB2_TRANSFORM header\n",
406 (unsigned long long)uid));
407 TALLOC_FREE(iov_alloc);
408 return NT_STATUS_USER_SESSION_DELETED;
411 tf_iov[0].iov_base = (void *)tf;
412 tf_iov[0].iov_len = tf_len;
413 tf_iov[1].iov_base = (void *)hdr;
414 tf_iov[1].iov_len = enc_len;
416 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
417 xconn->smb2.server.cipher,
418 tf_iov, 2);
419 if (!NT_STATUS_IS_OK(status)) {
420 TALLOC_FREE(iov_alloc);
421 return status;
424 verified_buflen = taken + enc_len;
425 len = enc_len;
429 * We need the header plus the body length field
432 if (len < SMB2_HDR_BODY + 2) {
433 DEBUG(10, ("%d bytes left, expected at least %d\n",
434 (int)len, SMB2_HDR_BODY));
435 goto inval;
437 if (IVAL(hdr, 0) != SMB2_MAGIC) {
438 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
439 IVAL(hdr, 0)));
440 goto inval;
442 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
443 DEBUG(10, ("Got HDR len %d, expected %d\n",
444 SVAL(hdr, 4), SMB2_HDR_BODY));
445 goto inval;
448 full_size = len;
449 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
450 body_size = SVAL(hdr, SMB2_HDR_BODY);
452 if (next_command_ofs != 0) {
453 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
454 goto inval;
456 if (next_command_ofs > full_size) {
457 goto inval;
459 full_size = next_command_ofs;
461 if (body_size < 2) {
462 goto inval;
464 body_size &= 0xfffe;
466 if (body_size > (full_size - SMB2_HDR_BODY)) {
468 * let the caller handle the error
470 body_size = full_size - SMB2_HDR_BODY;
472 body = hdr + SMB2_HDR_BODY;
473 dyn = body + body_size;
474 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
476 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
477 struct iovec *iov_tmp = NULL;
479 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
480 struct iovec,
481 num_iov +
482 SMBD_SMB2_NUM_IOV_PER_REQ);
483 if (iov_tmp == NULL) {
484 TALLOC_FREE(iov_alloc);
485 return NT_STATUS_NO_MEMORY;
488 if (iov_alloc == NULL) {
489 memcpy(iov_tmp,
490 req->in._vector,
491 sizeof(req->in._vector));
494 iov = iov_tmp;
496 cur = &iov[num_iov];
497 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
499 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
500 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
501 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
502 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
503 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
504 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
505 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
506 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
508 taken += full_size;
511 *piov = iov;
512 *pnum_iov = num_iov;
513 return NT_STATUS_OK;
515 inval:
516 if (iov != req->in._vector) {
517 TALLOC_FREE(iov);
519 return NT_STATUS_INVALID_PARAMETER;
522 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
523 const uint8_t *_inpdu, size_t size,
524 struct smbd_smb2_request **_req)
526 struct smbd_server_connection *sconn = xconn->client->sconn;
527 struct smbd_smb2_request *req;
528 uint32_t protocol_version;
529 uint8_t *inpdu = NULL;
530 const uint8_t *inhdr = NULL;
531 uint16_t cmd;
532 uint32_t next_command_ofs;
533 NTSTATUS status;
534 NTTIME now;
536 if (size < (SMB2_HDR_BODY + 2)) {
537 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
538 return NT_STATUS_INVALID_PARAMETER;
541 inhdr = _inpdu;
543 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
544 if (protocol_version != SMB2_MAGIC) {
545 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
546 protocol_version));
547 return NT_STATUS_INVALID_PARAMETER;
550 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
551 if (cmd != SMB2_OP_NEGPROT) {
552 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
553 cmd));
554 return NT_STATUS_INVALID_PARAMETER;
557 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
558 if (next_command_ofs != 0) {
559 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
560 next_command_ofs));
561 return NT_STATUS_INVALID_PARAMETER;
564 req = smbd_smb2_request_allocate(xconn);
565 if (req == NULL) {
566 return NT_STATUS_NO_MEMORY;
568 req->sconn = sconn;
569 req->xconn = xconn;
571 inpdu = talloc_memdup(req, _inpdu, size);
572 if (inpdu == NULL) {
573 return NT_STATUS_NO_MEMORY;
576 req->request_time = timeval_current();
577 now = timeval_to_nttime(&req->request_time);
579 status = smbd_smb2_inbuf_parse_compound(xconn,
580 now,
581 inpdu,
582 size,
583 req, &req->in.vector,
584 &req->in.vector_count);
585 if (!NT_STATUS_IS_OK(status)) {
586 TALLOC_FREE(req);
587 return status;
590 req->current_idx = 1;
592 *_req = req;
593 return NT_STATUS_OK;
596 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
597 uint64_t message_id, uint64_t seq_id)
599 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
600 unsigned int offset;
601 uint64_t seq_tmp;
603 seq_tmp = xconn->smb2.credits.seq_low;
604 if (seq_id < seq_tmp) {
605 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
606 "%llu (sequence id %llu) "
607 "(granted = %u, low = %llu, range = %u)\n",
608 (unsigned long long)message_id,
609 (unsigned long long)seq_id,
610 (unsigned int)xconn->smb2.credits.granted,
611 (unsigned long long)xconn->smb2.credits.seq_low,
612 (unsigned int)xconn->smb2.credits.seq_range));
613 return false;
616 seq_tmp += xconn->smb2.credits.seq_range;
617 if (seq_id >= seq_tmp) {
618 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
619 "%llu (sequence id %llu) "
620 "(granted = %u, low = %llu, range = %u)\n",
621 (unsigned long long)message_id,
622 (unsigned long long)seq_id,
623 (unsigned int)xconn->smb2.credits.granted,
624 (unsigned long long)xconn->smb2.credits.seq_low,
625 (unsigned int)xconn->smb2.credits.seq_range));
626 return false;
629 offset = seq_id % xconn->smb2.credits.max;
631 if (bitmap_query(credits_bm, offset)) {
632 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
633 "%llu (sequence id %llu) "
634 "(granted = %u, low = %llu, range = %u) "
635 "(bm offset %u)\n",
636 (unsigned long long)message_id,
637 (unsigned long long)seq_id,
638 (unsigned int)xconn->smb2.credits.granted,
639 (unsigned long long)xconn->smb2.credits.seq_low,
640 (unsigned int)xconn->smb2.credits.seq_range,
641 offset));
642 return false;
645 /* Mark the message_ids as seen in the bitmap. */
646 bitmap_set(credits_bm, offset);
648 if (seq_id != xconn->smb2.credits.seq_low) {
649 return true;
653 * Move the window forward by all the message_id's
654 * already seen.
656 while (bitmap_query(credits_bm, offset)) {
657 DEBUG(10,("smb2_validate_sequence_number: clearing "
658 "id %llu (position %u) from bitmap\n",
659 (unsigned long long)(xconn->smb2.credits.seq_low),
660 offset));
661 bitmap_clear(credits_bm, offset);
663 xconn->smb2.credits.seq_low += 1;
664 xconn->smb2.credits.seq_range -= 1;
665 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
668 return true;
671 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
672 const uint8_t *inhdr)
674 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
675 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
676 uint16_t credit_charge = 1;
677 uint64_t i;
679 if (opcode == SMB2_OP_CANCEL) {
680 /* SMB2_CANCEL requests by definition resend messageids. */
681 return true;
684 if (xconn->smb2.credits.multicredit) {
685 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
686 credit_charge = MAX(credit_charge, 1);
689 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
690 "credits_granted %llu, "
691 "seqnum low/range: %llu/%llu\n",
692 (unsigned long long) message_id,
693 (unsigned long long) credit_charge,
694 (unsigned long long) xconn->smb2.credits.granted,
695 (unsigned long long) xconn->smb2.credits.seq_low,
696 (unsigned long long) xconn->smb2.credits.seq_range));
698 if (xconn->smb2.credits.granted < credit_charge) {
699 DEBUG(0, ("smb2_validate_message_id: client used more "
700 "credits than granted, 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));
708 return false;
712 * now check the message ids
714 * for multi-credit requests we need to check all current mid plus
715 * the implicit mids caused by the credit charge
716 * e.g. current mid = 15, charge 5 => mark 15-19 as used
719 for (i = 0; i <= (credit_charge-1); i++) {
720 uint64_t id = message_id + i;
721 bool ok;
723 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
724 (unsigned long long)message_id,
725 credit_charge,
726 (unsigned long long)id));
728 ok = smb2_validate_sequence_number(xconn, message_id, id);
729 if (!ok) {
730 return false;
734 /* substract used credits */
735 xconn->smb2.credits.granted -= credit_charge;
737 return true;
740 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
742 int count;
743 int idx;
745 count = req->in.vector_count;
747 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
748 /* It's not a SMB2 request */
749 return NT_STATUS_INVALID_PARAMETER;
752 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
753 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
754 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
755 const uint8_t *inhdr = NULL;
757 if (hdr->iov_len != SMB2_HDR_BODY) {
758 return NT_STATUS_INVALID_PARAMETER;
761 if (body->iov_len < 2) {
762 return NT_STATUS_INVALID_PARAMETER;
765 inhdr = (const uint8_t *)hdr->iov_base;
767 /* Check the SMB2 header */
768 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
769 return NT_STATUS_INVALID_PARAMETER;
772 if (!smb2_validate_message_id(req->xconn, inhdr)) {
773 return NT_STATUS_INVALID_PARAMETER;
777 return NT_STATUS_OK;
780 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
781 const struct iovec *in_vector,
782 struct iovec *out_vector)
784 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
785 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
786 uint16_t credit_charge = 1;
787 uint16_t credits_requested;
788 uint32_t out_flags;
789 uint16_t cmd;
790 NTSTATUS out_status;
791 uint16_t credits_granted = 0;
792 uint64_t credits_possible;
793 uint16_t current_max_credits;
796 * first we grant only 1/16th of the max range.
798 * Windows also starts with the 1/16th and then grants
799 * more later. I was only able to trigger higher
800 * values, when using a very high credit charge.
802 * TODO: scale up depending on load, free memory
803 * or other stuff.
804 * Maybe also on the relationship between number
805 * of requests and the used sequence number.
806 * Which means we would grant more credits
807 * for client which use multi credit requests.
809 current_max_credits = xconn->smb2.credits.max / 16;
810 current_max_credits = MAX(current_max_credits, 1);
812 if (xconn->smb2.credits.multicredit) {
813 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
814 credit_charge = MAX(credit_charge, 1);
817 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
818 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
819 credits_requested = MAX(credits_requested, 1);
820 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
821 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
823 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
825 if (xconn->smb2.credits.max < credit_charge) {
826 smbd_server_connection_terminate(xconn,
827 "client error: credit charge > max credits\n");
828 return;
831 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
833 * In case we already send an async interim
834 * response, we should not grant
835 * credits on the final response.
837 credits_granted = 0;
838 } else {
839 uint16_t additional_possible =
840 xconn->smb2.credits.max - credit_charge;
841 uint16_t additional_max = 0;
842 uint16_t additional_credits = credits_requested - 1;
844 switch (cmd) {
845 case SMB2_OP_NEGPROT:
846 break;
847 case SMB2_OP_SESSSETUP:
849 * Windows 2012 RC1 starts to grant
850 * additional credits
851 * with a successful session setup
853 if (NT_STATUS_IS_OK(out_status)) {
854 additional_max = 32;
856 break;
857 default:
859 * We match windows and only grant additional credits
860 * in chunks of 32.
862 additional_max = 32;
863 break;
866 additional_max = MIN(additional_max, additional_possible);
867 additional_credits = MIN(additional_credits, additional_max);
869 credits_granted = credit_charge + additional_credits;
873 * sequence numbers should not wrap
875 * 1. calculate the possible credits until
876 * the sequence numbers start to wrap on 64-bit.
878 * 2. UINT64_MAX is used for Break Notifications.
880 * 2. truncate the possible credits to the maximum
881 * credits we want to grant to the client in total.
883 * 3. remove the range we'll already granted to the client
884 * this makes sure the client consumes the lowest sequence
885 * number, before we can grant additional credits.
887 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
888 if (credits_possible > 0) {
889 /* remove UINT64_MAX */
890 credits_possible -= 1;
892 credits_possible = MIN(credits_possible, current_max_credits);
893 credits_possible -= xconn->smb2.credits.seq_range;
895 credits_granted = MIN(credits_granted, credits_possible);
897 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
898 xconn->smb2.credits.granted += credits_granted;
899 xconn->smb2.credits.seq_range += credits_granted;
901 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
902 "granted %u, current possible/max %u/%u, "
903 "total granted/max/low/range %u/%u/%llu/%u\n",
904 (unsigned int)credits_requested,
905 (unsigned int)credit_charge,
906 (unsigned int)credits_granted,
907 (unsigned int)credits_possible,
908 (unsigned int)current_max_credits,
909 (unsigned int)xconn->smb2.credits.granted,
910 (unsigned int)xconn->smb2.credits.max,
911 (unsigned long long)xconn->smb2.credits.seq_low,
912 (unsigned int)xconn->smb2.credits.seq_range));
915 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
916 struct smbd_smb2_request *outreq)
918 int count, idx;
919 uint16_t total_credits = 0;
921 count = outreq->out.vector_count;
923 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
924 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
925 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
926 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
928 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
930 /* To match Windows, count up what we
931 just granted. */
932 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
933 /* Set to zero in all but the last reply. */
934 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
935 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
936 } else {
937 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
942 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
944 if (req->current_idx <= 1) {
945 if (size <= sizeof(req->out._body)) {
946 return data_blob_const(req->out._body, size);
950 return data_blob_talloc(req, NULL, size);
953 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
955 struct smbXsrv_connection *xconn = req->xconn;
956 TALLOC_CTX *mem_ctx;
957 struct iovec *vector;
958 int count;
959 int idx;
960 bool ok;
962 count = req->in.vector_count;
963 if (count <= ARRAY_SIZE(req->out._vector)) {
964 mem_ctx = req;
965 vector = req->out._vector;
966 } else {
967 vector = talloc_zero_array(req, struct iovec, count);
968 if (vector == NULL) {
969 return NT_STATUS_NO_MEMORY;
971 mem_ctx = vector;
974 vector[0].iov_base = req->out.nbt_hdr;
975 vector[0].iov_len = 4;
976 SIVAL(req->out.nbt_hdr, 0, 0);
978 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
979 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
980 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
981 uint8_t *outhdr = NULL;
982 uint8_t *outbody = NULL;
983 uint32_t next_command_ofs = 0;
984 struct iovec *current = &vector[idx];
986 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
987 /* we have a next command -
988 * setup for the error case. */
989 next_command_ofs = SMB2_HDR_BODY + 9;
992 if (idx == 1) {
993 outhdr = req->out._hdr;
994 } else {
995 outhdr = talloc_zero_array(mem_ctx, uint8_t,
996 OUTVEC_ALLOC_SIZE);
997 if (outhdr == NULL) {
998 return NT_STATUS_NO_MEMORY;
1002 outbody = outhdr + SMB2_HDR_BODY;
1005 * SMBD_SMB2_TF_IOV_OFS might be used later
1007 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1008 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1010 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1011 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1013 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1014 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1016 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1017 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1019 /* setup the SMB2 header */
1020 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1021 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1022 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1023 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1024 SIVAL(outhdr, SMB2_HDR_STATUS,
1025 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1026 SSVAL(outhdr, SMB2_HDR_OPCODE,
1027 SVAL(inhdr, SMB2_HDR_OPCODE));
1028 SIVAL(outhdr, SMB2_HDR_FLAGS,
1029 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1030 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1031 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1032 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1033 SIVAL(outhdr, SMB2_HDR_PID,
1034 IVAL(inhdr, SMB2_HDR_PID));
1035 SIVAL(outhdr, SMB2_HDR_TID,
1036 IVAL(inhdr, SMB2_HDR_TID));
1037 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1038 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1039 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1040 inhdr + SMB2_HDR_SIGNATURE, 16);
1042 /* setup error body header */
1043 SSVAL(outbody, 0x00, 0x08 + 1);
1044 SSVAL(outbody, 0x02, 0);
1045 SIVAL(outbody, 0x04, 0);
1048 req->out.vector = vector;
1049 req->out.vector_count = count;
1051 /* setup the length of the NBT packet */
1052 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1053 if (!ok) {
1054 return NT_STATUS_INVALID_PARAMETER_MIX;
1057 DLIST_ADD_END(xconn->smb2.requests, req);
1059 return NT_STATUS_OK;
1062 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1063 const char *reason,
1064 const char *location)
1066 struct smbXsrv_client *client = xconn->client;
1068 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1069 smbXsrv_connection_dbg(xconn), reason, location));
1071 if (client->connections->next != NULL) {
1072 /* TODO: cancel pending requests */
1073 DLIST_REMOVE(client->connections, xconn);
1074 TALLOC_FREE(xconn);
1075 return;
1079 * The last connection was disconnected
1081 exit_server_cleanly(reason);
1084 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1085 struct iovec *outvec,
1086 const struct iovec *srcvec)
1088 const uint8_t *srctf;
1089 size_t srctf_len;
1090 const uint8_t *srchdr;
1091 size_t srchdr_len;
1092 const uint8_t *srcbody;
1093 size_t srcbody_len;
1094 const uint8_t *expected_srcbody;
1095 const uint8_t *srcdyn;
1096 size_t srcdyn_len;
1097 const uint8_t *expected_srcdyn;
1098 uint8_t *dsttf;
1099 uint8_t *dsthdr;
1100 uint8_t *dstbody;
1101 uint8_t *dstdyn;
1103 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1104 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1105 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1106 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1107 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1108 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1109 expected_srcbody = srchdr + SMB2_HDR_BODY;
1110 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1111 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1112 expected_srcdyn = srcbody + 8;
1114 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1115 return false;
1118 if (srchdr_len != SMB2_HDR_BODY) {
1119 return false;
1122 if (srctf_len == SMB2_TF_HDR_SIZE) {
1123 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1124 if (dsttf == NULL) {
1125 return false;
1127 } else {
1128 dsttf = NULL;
1130 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1131 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1133 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1134 * be allocated with size OUTVEC_ALLOC_SIZE. */
1136 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1137 if (dsthdr == NULL) {
1138 return false;
1140 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1141 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1144 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1145 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1146 * then duplicate this. Else use talloc_memdup().
1149 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1150 dstbody = dsthdr + SMB2_HDR_BODY;
1151 } else {
1152 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1153 if (dstbody == NULL) {
1154 return false;
1157 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1158 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1161 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1162 * pointing to
1163 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1164 * then duplicate this. Else use talloc_memdup().
1167 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1168 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1169 } else if (srcdyn == NULL) {
1170 dstdyn = NULL;
1171 } else {
1172 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1173 if (dstdyn == NULL) {
1174 return false;
1177 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1178 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1180 return true;
1183 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1185 struct smbd_smb2_request *newreq = NULL;
1186 struct iovec *outvec = NULL;
1187 int count = req->out.vector_count;
1188 int i;
1189 bool ok;
1191 newreq = smbd_smb2_request_allocate(req->xconn);
1192 if (!newreq) {
1193 return NULL;
1196 newreq->sconn = req->sconn;
1197 newreq->xconn = req->xconn;
1198 newreq->session = req->session;
1199 newreq->do_encryption = req->do_encryption;
1200 newreq->do_signing = req->do_signing;
1201 newreq->current_idx = req->current_idx;
1203 outvec = talloc_zero_array(newreq, struct iovec, count);
1204 if (!outvec) {
1205 TALLOC_FREE(newreq);
1206 return NULL;
1208 newreq->out.vector = outvec;
1209 newreq->out.vector_count = count;
1211 /* Setup the outvec's identically to req. */
1212 outvec[0].iov_base = newreq->out.nbt_hdr;
1213 outvec[0].iov_len = 4;
1214 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1216 /* Setup the vectors identically to the ones in req. */
1217 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1218 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1219 break;
1223 if (i < count) {
1224 /* Alloc failed. */
1225 TALLOC_FREE(newreq);
1226 return NULL;
1229 ok = smb2_setup_nbt_length(newreq->out.vector,
1230 newreq->out.vector_count);
1231 if (!ok) {
1232 TALLOC_FREE(newreq);
1233 return NULL;
1236 return newreq;
1239 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1241 struct smbXsrv_connection *xconn = req->xconn;
1242 int first_idx = 1;
1243 struct iovec *firsttf = NULL;
1244 struct iovec *outhdr_v = NULL;
1245 uint8_t *outhdr = NULL;
1246 struct smbd_smb2_request *nreq = NULL;
1247 NTSTATUS status;
1248 bool ok;
1250 /* Create a new smb2 request we'll use
1251 for the interim return. */
1252 nreq = dup_smb2_req(req);
1253 if (!nreq) {
1254 return NT_STATUS_NO_MEMORY;
1257 /* Lose the last X out vectors. They're the
1258 ones we'll be using for the async reply. */
1259 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1261 ok = smb2_setup_nbt_length(nreq->out.vector,
1262 nreq->out.vector_count);
1263 if (!ok) {
1264 return NT_STATUS_INVALID_PARAMETER_MIX;
1267 /* Step back to the previous reply. */
1268 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1269 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1270 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1271 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1272 /* And end the chain. */
1273 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1275 /* Calculate outgoing credits */
1276 smb2_calculate_credits(req, nreq);
1278 if (DEBUGLEVEL >= 10) {
1279 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1280 (unsigned int)nreq->current_idx );
1281 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1282 (unsigned int)nreq->out.vector_count );
1283 print_req_vectors(nreq);
1287 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1288 * we need to sign/encrypt here with the last/first key we remembered
1290 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1291 status = smb2_signing_encrypt_pdu(req->first_key,
1292 xconn->smb2.server.cipher,
1293 firsttf,
1294 nreq->out.vector_count - first_idx);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 return status;
1298 } else if (req->last_key.length > 0) {
1299 status = smb2_signing_sign_pdu(req->last_key,
1300 xconn->protocol,
1301 outhdr_v,
1302 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 return status;
1308 nreq->queue_entry.mem_ctx = nreq;
1309 nreq->queue_entry.vector = nreq->out.vector;
1310 nreq->queue_entry.count = nreq->out.vector_count;
1311 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1312 xconn->smb2.send_queue_len++;
1314 status = smbd_smb2_flush_send_queue(xconn);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 return status;
1319 return NT_STATUS_OK;
1322 struct smbd_smb2_request_pending_state {
1323 struct smbd_smb2_send_queue queue_entry;
1324 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1325 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1328 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1329 struct tevent_timer *te,
1330 struct timeval current_time,
1331 void *private_data);
1333 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1334 struct tevent_req *subreq,
1335 uint32_t defer_time)
1337 NTSTATUS status;
1338 struct timeval defer_endtime;
1339 uint8_t *outhdr = NULL;
1340 uint32_t flags;
1342 if (!tevent_req_is_in_progress(subreq)) {
1344 * This is a performance optimization,
1345 * it avoids one tevent_loop iteration,
1346 * which means we avoid one
1347 * talloc_stackframe_pool/talloc_free pair.
1349 tevent_req_notify_callback(subreq);
1350 return NT_STATUS_OK;
1353 req->subreq = subreq;
1354 subreq = NULL;
1356 if (req->async_te) {
1357 /* We're already async. */
1358 return NT_STATUS_OK;
1361 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1362 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1363 if (flags & SMB2_HDR_FLAG_ASYNC) {
1364 /* We're already async. */
1365 return NT_STATUS_OK;
1368 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1370 * We're trying to go async in a compound request
1371 * chain. This is only allowed for opens that cause an
1372 * oplock break or for the last operation in the
1373 * chain, otherwise it is not allowed. See
1374 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1376 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1378 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1380 * Cancel the outstanding request.
1382 bool ok = tevent_req_cancel(req->subreq);
1383 if (ok) {
1384 return NT_STATUS_OK;
1386 TALLOC_FREE(req->subreq);
1387 return smbd_smb2_request_error(req,
1388 NT_STATUS_INTERNAL_ERROR);
1392 if (DEBUGLEVEL >= 10) {
1393 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1394 (unsigned int)req->current_idx );
1395 print_req_vectors(req);
1398 if (req->current_idx > 1) {
1400 * We're going async in a compound
1401 * chain after the first request has
1402 * already been processed. Send an
1403 * interim response containing the
1404 * set of replies already generated.
1406 int idx = req->current_idx;
1408 status = smb2_send_async_interim_response(req);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 return status;
1412 if (req->first_key.length > 0) {
1413 data_blob_clear_free(&req->first_key);
1416 req->current_idx = 1;
1419 * Re-arrange the in.vectors to remove what
1420 * we just sent.
1422 memmove(&req->in.vector[1],
1423 &req->in.vector[idx],
1424 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1425 req->in.vector_count = 1 + (req->in.vector_count - idx);
1427 /* Re-arrange the out.vectors to match. */
1428 memmove(&req->out.vector[1],
1429 &req->out.vector[idx],
1430 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1431 req->out.vector_count = 1 + (req->out.vector_count - idx);
1433 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1435 * We only have one remaining request as
1436 * we've processed everything else.
1437 * This is no longer a compound request.
1439 req->compound_related = false;
1440 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1441 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1442 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1445 if (req->last_key.length > 0) {
1446 data_blob_clear_free(&req->last_key);
1449 defer_endtime = timeval_current_ofs_usec(defer_time);
1450 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1451 req, defer_endtime,
1452 smbd_smb2_request_pending_timer,
1453 req);
1454 if (req->async_te == NULL) {
1455 return NT_STATUS_NO_MEMORY;
1458 return NT_STATUS_OK;
1461 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1462 struct smbXsrv_connection *xconn)
1464 struct smbXsrv_channel_global0 *c = NULL;
1465 NTSTATUS status;
1466 DATA_BLOB key = data_blob_null;
1468 status = smbXsrv_session_find_channel(session, xconn, &c);
1469 if (NT_STATUS_IS_OK(status)) {
1470 key = c->signing_key;
1473 if (key.length == 0) {
1474 key = session->global->signing_key;
1477 return key;
1480 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1481 uint64_t *new_nonce_high,
1482 uint64_t *new_nonce_low)
1484 uint64_t nonce_high;
1485 uint64_t nonce_low;
1487 session->nonce_low += 1;
1488 if (session->nonce_low == 0) {
1489 session->nonce_low += 1;
1490 session->nonce_high += 1;
1494 * CCM and GCM algorithms must never have their
1495 * nonce wrap, or the security of the whole
1496 * communication and the keys is destroyed.
1497 * We must drop the connection once we have
1498 * transfered too much data.
1500 * NOTE: We assume nonces greater than 8 bytes.
1502 if (session->nonce_high >= session->nonce_high_max) {
1503 return NT_STATUS_ENCRYPTION_FAILED;
1506 nonce_high = session->nonce_high_random;
1507 nonce_high += session->nonce_high;
1508 nonce_low = session->nonce_low;
1510 *new_nonce_high = nonce_high;
1511 *new_nonce_low = nonce_low;
1512 return NT_STATUS_OK;
1515 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1516 struct tevent_timer *te,
1517 struct timeval current_time,
1518 void *private_data)
1520 struct smbd_smb2_request *req =
1521 talloc_get_type_abort(private_data,
1522 struct smbd_smb2_request);
1523 struct smbXsrv_connection *xconn = req->xconn;
1524 struct smbd_smb2_request_pending_state *state = NULL;
1525 uint8_t *outhdr = NULL;
1526 const uint8_t *inhdr = NULL;
1527 uint8_t *tf = NULL;
1528 size_t tf_len = 0;
1529 uint8_t *hdr = NULL;
1530 uint8_t *body = NULL;
1531 uint8_t *dyn = NULL;
1532 uint32_t flags = 0;
1533 uint64_t session_id = 0;
1534 uint64_t message_id = 0;
1535 uint64_t nonce_high = 0;
1536 uint64_t nonce_low = 0;
1537 uint64_t async_id = 0;
1538 NTSTATUS status;
1539 bool ok;
1541 TALLOC_FREE(req->async_te);
1543 /* Ensure our final reply matches the interim one. */
1544 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1545 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1546 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1547 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1548 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1550 async_id = message_id; /* keep it simple for now... */
1552 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1553 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1555 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1556 "going async\n",
1557 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1558 (unsigned long long)async_id ));
1561 * What we send is identical to a smbd_smb2_request_error
1562 * packet with an error status of STATUS_PENDING. Make use
1563 * of this fact sometime when refactoring. JRA.
1566 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1567 if (state == NULL) {
1568 smbd_server_connection_terminate(xconn,
1569 nt_errstr(NT_STATUS_NO_MEMORY));
1570 return;
1573 tf = state->buf + NBT_HDR_SIZE;
1574 tf_len = SMB2_TF_HDR_SIZE;
1576 hdr = tf + SMB2_TF_HDR_SIZE;
1577 body = hdr + SMB2_HDR_BODY;
1578 dyn = body + 8;
1580 if (req->do_encryption) {
1581 status = smb2_get_new_nonce(req->session,
1582 &nonce_high,
1583 &nonce_low);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 smbd_server_connection_terminate(xconn,
1586 nt_errstr(status));
1587 return;
1591 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1592 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1593 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1594 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1596 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1597 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1598 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1599 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1600 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1602 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1603 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1604 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1605 SBVAL(hdr, SMB2_HDR_PID, async_id);
1606 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1607 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1608 memcpy(hdr+SMB2_HDR_SIGNATURE,
1609 outhdr+SMB2_HDR_SIGNATURE, 16);
1611 SSVAL(body, 0x00, 0x08 + 1);
1613 SCVAL(body, 0x02, 0);
1614 SCVAL(body, 0x03, 0);
1615 SIVAL(body, 0x04, 0);
1616 /* Match W2K8R2... */
1617 SCVAL(dyn, 0x00, 0x21);
1619 state->vector[0].iov_base = (void *)state->buf;
1620 state->vector[0].iov_len = NBT_HDR_SIZE;
1622 if (req->do_encryption) {
1623 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1624 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1625 } else {
1626 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1627 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1630 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1631 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1633 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1634 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1636 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1637 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1639 ok = smb2_setup_nbt_length(state->vector,
1640 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1641 if (!ok) {
1642 smbd_server_connection_terminate(
1643 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1644 return;
1647 /* Ensure we correctly go through crediting. Grant
1648 the credits now, and zero credits on the final
1649 response. */
1650 smb2_set_operation_credit(req->xconn,
1651 SMBD_SMB2_IN_HDR_IOV(req),
1652 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1654 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1656 if (DEBUGLVL(10)) {
1657 int i;
1659 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1660 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1661 (unsigned int)i,
1662 (unsigned int)ARRAY_SIZE(state->vector),
1663 (unsigned int)state->vector[i].iov_len);
1667 if (req->do_encryption) {
1668 struct smbXsrv_session *x = req->session;
1669 DATA_BLOB encryption_key = x->global->encryption_key;
1671 status = smb2_signing_encrypt_pdu(encryption_key,
1672 xconn->smb2.server.cipher,
1673 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1674 SMBD_SMB2_NUM_IOV_PER_REQ);
1675 if (!NT_STATUS_IS_OK(status)) {
1676 smbd_server_connection_terminate(xconn,
1677 nt_errstr(status));
1678 return;
1680 } else if (req->do_signing) {
1681 struct smbXsrv_session *x = req->session;
1682 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1684 status = smb2_signing_sign_pdu(signing_key,
1685 xconn->protocol,
1686 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1687 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 smbd_server_connection_terminate(xconn,
1690 nt_errstr(status));
1691 return;
1695 state->queue_entry.mem_ctx = state;
1696 state->queue_entry.vector = state->vector;
1697 state->queue_entry.count = ARRAY_SIZE(state->vector);
1698 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1699 xconn->smb2.send_queue_len++;
1701 status = smbd_smb2_flush_send_queue(xconn);
1702 if (!NT_STATUS_IS_OK(status)) {
1703 smbd_server_connection_terminate(xconn,
1704 nt_errstr(status));
1705 return;
1709 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1711 struct smbXsrv_connection *xconn = req->xconn;
1712 struct smbd_smb2_request *cur;
1713 const uint8_t *inhdr;
1714 uint32_t flags;
1715 uint64_t search_message_id;
1716 uint64_t search_async_id;
1717 uint64_t found_id;
1719 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1721 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1722 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1723 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1726 * We don't need the request anymore cancel requests never
1727 * have a response.
1729 * We defer the TALLOC_FREE(req) to the caller.
1731 DLIST_REMOVE(xconn->smb2.requests, req);
1733 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1734 const uint8_t *outhdr;
1735 uint64_t message_id;
1736 uint64_t async_id;
1738 if (cur->compound_related) {
1740 * Never cancel anything in a compound request.
1741 * Way too hard to deal with the result.
1743 continue;
1746 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1748 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1749 async_id = BVAL(outhdr, SMB2_HDR_PID);
1751 if (flags & SMB2_HDR_FLAG_ASYNC) {
1752 if (search_async_id == async_id) {
1753 found_id = async_id;
1754 break;
1756 } else {
1757 if (search_message_id == message_id) {
1758 found_id = message_id;
1759 break;
1764 if (cur && cur->subreq) {
1765 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1766 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1767 "cancel opcode[%s] mid %llu\n",
1768 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1769 (unsigned long long)found_id ));
1770 tevent_req_cancel(cur->subreq);
1773 return NT_STATUS_OK;
1776 /*************************************************************
1777 Ensure an incoming tid is a valid one for us to access.
1778 Change to the associated uid credentials and chdir to the
1779 valid tid directory.
1780 *************************************************************/
1782 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1784 const uint8_t *inhdr;
1785 uint32_t in_flags;
1786 uint32_t in_tid;
1787 struct smbXsrv_tcon *tcon;
1788 NTSTATUS status;
1789 NTTIME now = timeval_to_nttime(&req->request_time);
1791 req->tcon = NULL;
1793 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1795 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1796 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1798 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1799 in_tid = req->last_tid;
1802 req->last_tid = 0;
1804 status = smb2srv_tcon_lookup(req->session,
1805 in_tid, now, &tcon);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 return status;
1810 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1811 return NT_STATUS_ACCESS_DENIED;
1814 if (!set_current_service(tcon->compat, 0, true)) {
1815 return NT_STATUS_ACCESS_DENIED;
1818 req->tcon = tcon;
1819 req->last_tid = in_tid;
1821 return NT_STATUS_OK;
1824 /*************************************************************
1825 Ensure an incoming session_id is a valid one for us to access.
1826 *************************************************************/
1828 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1830 const uint8_t *inhdr;
1831 uint32_t in_flags;
1832 uint16_t in_opcode;
1833 uint64_t in_session_id;
1834 struct smbXsrv_session *session = NULL;
1835 struct auth_session_info *session_info;
1836 NTSTATUS status;
1837 NTTIME now = timeval_to_nttime(&req->request_time);
1839 req->session = NULL;
1840 req->tcon = NULL;
1842 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1844 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1845 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1846 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1848 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1849 in_session_id = req->last_session_id;
1852 req->last_session_id = 0;
1854 /* look an existing session up */
1855 switch (in_opcode) {
1856 case SMB2_OP_SESSSETUP:
1858 * For a session bind request, we don't have the
1859 * channel set up at this point yet, so we defer
1860 * the verification that the connection belongs
1861 * to the session to the session setup code, which
1862 * can look at the session binding flags.
1864 status = smb2srv_session_lookup_client(req->xconn->client,
1865 in_session_id, now,
1866 &session);
1867 break;
1868 default:
1869 status = smb2srv_session_lookup_conn(req->xconn,
1870 in_session_id, now,
1871 &session);
1872 break;
1874 if (session) {
1875 req->session = session;
1876 req->last_session_id = in_session_id;
1878 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1879 switch (in_opcode) {
1880 case SMB2_OP_SESSSETUP:
1881 status = NT_STATUS_OK;
1882 break;
1883 default:
1884 break;
1887 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1888 switch (in_opcode) {
1889 case SMB2_OP_TCON:
1890 case SMB2_OP_CREATE:
1891 case SMB2_OP_GETINFO:
1892 case SMB2_OP_SETINFO:
1893 return NT_STATUS_INVALID_HANDLE;
1894 default:
1896 * Notice the check for
1897 * (session_info == NULL)
1898 * below.
1900 status = NT_STATUS_OK;
1901 break;
1904 if (!NT_STATUS_IS_OK(status)) {
1905 return status;
1908 session_info = session->global->auth_session_info;
1909 if (session_info == NULL) {
1910 return NT_STATUS_INVALID_HANDLE;
1913 if (in_session_id != req->xconn->client->last_session_id) {
1914 req->xconn->client->last_session_id = in_session_id;
1915 set_current_user_info(session_info->unix_info->sanitized_username,
1916 session_info->unix_info->unix_name,
1917 session_info->info->domain_name);
1920 return NT_STATUS_OK;
1923 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1924 uint32_t data_length)
1926 struct smbXsrv_connection *xconn = req->xconn;
1927 uint16_t needed_charge;
1928 uint16_t credit_charge = 1;
1929 const uint8_t *inhdr;
1931 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1933 if (xconn->smb2.credits.multicredit) {
1934 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1935 credit_charge = MAX(credit_charge, 1);
1938 needed_charge = (data_length - 1)/ 65536 + 1;
1940 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1941 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1942 credit_charge, needed_charge));
1944 if (needed_charge > credit_charge) {
1945 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1946 credit_charge, needed_charge));
1947 return NT_STATUS_INVALID_PARAMETER;
1950 return NT_STATUS_OK;
1953 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1954 size_t expected_body_size)
1956 struct iovec *inhdr_v;
1957 const uint8_t *inhdr;
1958 uint16_t opcode;
1959 const uint8_t *inbody;
1960 size_t body_size;
1961 size_t min_dyn_size = expected_body_size & 0x00000001;
1962 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1965 * The following should be checked already.
1967 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1968 return NT_STATUS_INTERNAL_ERROR;
1970 if (req->current_idx > max_idx) {
1971 return NT_STATUS_INTERNAL_ERROR;
1974 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1975 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1976 return NT_STATUS_INTERNAL_ERROR;
1978 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1979 return NT_STATUS_INTERNAL_ERROR;
1982 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1983 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1985 switch (opcode) {
1986 case SMB2_OP_IOCTL:
1987 case SMB2_OP_GETINFO:
1988 min_dyn_size = 0;
1989 break;
1990 case SMB2_OP_WRITE:
1991 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1992 if (req->smb1req->unread_bytes < min_dyn_size) {
1993 return NT_STATUS_INVALID_PARAMETER;
1996 min_dyn_size = 0;
1998 break;
2002 * Now check the expected body size,
2003 * where the last byte might be in the
2004 * dynamic section..
2006 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2007 return NT_STATUS_INVALID_PARAMETER;
2009 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2010 return NT_STATUS_INVALID_PARAMETER;
2013 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2015 body_size = SVAL(inbody, 0x00);
2016 if (body_size != expected_body_size) {
2017 return NT_STATUS_INVALID_PARAMETER;
2020 return NT_STATUS_OK;
2023 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2025 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2027 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2028 SMBXSRV_ENCRYPTION_DESIRED |
2029 SMBXSRV_ENCRYPTION_REQUIRED)));
2032 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2034 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2035 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2038 /* Set a flag if not already set, return true if set */
2039 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2041 if ((flag == 0) || (*flags & flag)) {
2042 return false;
2045 *flags |= flag;
2046 return true;
2050 * Update encryption state tracking flags, this can be used to
2051 * determine whether whether the session or tcon is "encrypted".
2053 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2054 uint16_t opcode,
2055 bool *update_session_globalp,
2056 bool *update_tcon_globalp)
2058 /* Default: assume unecrypted and unsigned */
2059 struct smbXsrv_session *session = req->session;
2060 struct smbXsrv_tcon *tcon = req->tcon;
2061 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2062 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2063 bool update_session = false;
2064 bool update_tcon = false;
2066 if (req->was_encrypted && req->do_encryption) {
2067 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2068 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2069 } else {
2070 /* Unencrypted packet, can be signed */
2071 if (req->do_signing) {
2072 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2073 } else if (opcode == SMB2_OP_CANCEL) {
2074 /* Cancel requests are allowed to skip signing */
2075 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2079 update_session |= smbXsrv_set_crypto_flag(
2080 &session->global->encryption_flags, encrypt_flag);
2081 update_session |= smbXsrv_set_crypto_flag(
2082 &session->global->signing_flags, sign_flag);
2084 if (tcon) {
2085 update_tcon |= smbXsrv_set_crypto_flag(
2086 &tcon->global->encryption_flags, encrypt_flag);
2087 update_tcon |= smbXsrv_set_crypto_flag(
2088 &tcon->global->signing_flags, sign_flag);
2091 *update_session_globalp = update_session;
2092 *update_tcon_globalp = update_tcon;
2093 return;
2096 bool smbXsrv_is_signed(uint8_t signing_flags)
2099 * Signing is always enabled, so unless we got an unsigned
2100 * packet and at least one signed packet that was not
2101 * encrypted, the session or tcon is "signed".
2103 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2104 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2107 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2109 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2110 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2113 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2114 struct smbd_smb2_request *req,
2115 bool modify_call)
2117 struct smbXsrv_connection *xconn = req->xconn;
2118 const uint8_t *inhdr;
2119 uint16_t channel_sequence;
2120 uint32_t flags;
2121 int cmp;
2122 struct smbXsrv_open *op;
2123 bool update_open = false;
2124 NTSTATUS status = NT_STATUS_OK;
2126 req->request_counters_updated = false;
2128 if (xconn->protocol < PROTOCOL_SMB2_22) {
2129 return NT_STATUS_OK;
2132 if (req->compat_chain_fsp == NULL) {
2133 return NT_STATUS_OK;
2136 op = req->compat_chain_fsp->op;
2137 if (op == NULL) {
2138 return NT_STATUS_OK;
2141 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2142 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2143 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2145 cmp = channel_sequence - op->global->channel_sequence;
2147 if (abs(cmp) > INT16_MAX) {
2149 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2151 * If the channel sequence number of the request and the one
2152 * known to the server are not equal, the channel sequence
2153 * number and outstanding request counts are only updated
2154 * "... if the unsigned difference using 16-bit arithmetic
2155 * between ChannelSequence and Open.ChannelSequence is less than
2156 * or equal to 0x7FFF ...".
2157 * Otherwise, an error is returned for the modifying
2158 * calls write, set_info, and ioctl.
2160 * There are currently two issues with the description:
2162 * * For the other calls, the document seems to imply
2163 * that processing continues without adapting the
2164 * counters (if the sequence numbers are not equal).
2166 * TODO: This needs clarification!
2168 * * Also, the behaviour if the difference is larger
2169 * than 0x7FFF is not clear. The document seems to
2170 * imply that if such a difference is reached,
2171 * the server starts to ignore the counters or
2172 * in the case of the modifying calls, return errors.
2174 * TODO: This needs clarification!
2176 * At this point Samba tries to be a little more
2177 * clever than the description in the MS-SMB2 document
2178 * by heuristically detecting and properly treating
2179 * a 16 bit overflow of the client-submitted sequence
2180 * number:
2182 * If the stored channel squence number is more than
2183 * 0x7FFF larger than the one from the request, then
2184 * the client-provided sequence number has likely
2185 * overflown. We treat this case as valid instead
2186 * of as failure.
2188 * The MS-SMB2 behaviour would be setting cmp = -1.
2190 cmp *= -1;
2193 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2194 if (cmp == 0) {
2195 op->request_count += 1;
2196 req->request_counters_updated = true;
2197 } else if (cmp > 0) {
2198 op->pre_request_count += op->request_count;
2199 op->request_count = 1;
2200 op->global->channel_sequence = channel_sequence;
2201 update_open = true;
2202 req->request_counters_updated = true;
2203 } else if (modify_call) {
2204 return NT_STATUS_FILE_NOT_AVAILABLE;
2206 } else {
2207 if (cmp == 0 && op->pre_request_count == 0) {
2208 op->request_count += 1;
2209 req->request_counters_updated = true;
2210 } else if (cmp > 0 && op->pre_request_count == 0) {
2211 op->pre_request_count += op->request_count;
2212 op->request_count = 1;
2213 op->global->channel_sequence = channel_sequence;
2214 update_open = true;
2215 req->request_counters_updated = true;
2216 } else if (modify_call) {
2217 return NT_STATUS_FILE_NOT_AVAILABLE;
2221 if (update_open) {
2222 status = smbXsrv_open_update(op);
2225 return status;
2228 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2230 struct smbXsrv_connection *xconn = req->xconn;
2231 const struct smbd_smb2_dispatch_table *call = NULL;
2232 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2233 const uint8_t *inhdr;
2234 uint16_t opcode;
2235 uint32_t flags;
2236 uint64_t mid;
2237 NTSTATUS status;
2238 NTSTATUS session_status;
2239 uint32_t allowed_flags;
2240 NTSTATUS return_value;
2241 struct smbXsrv_session *x = NULL;
2242 bool signing_required = false;
2243 bool encryption_desired = false;
2244 bool encryption_required = false;
2246 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2248 DO_PROFILE_INC(request);
2250 /* TODO: verify more things */
2252 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2253 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2254 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2255 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2256 smb2_opcode_name(opcode),
2257 (unsigned long long)mid));
2259 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2261 * once the protocol is negotiated
2262 * SMB2_OP_NEGPROT is not allowed anymore
2264 if (opcode == SMB2_OP_NEGPROT) {
2265 /* drop the connection */
2266 return NT_STATUS_INVALID_PARAMETER;
2268 } else {
2270 * if the protocol is not negotiated yet
2271 * only SMB2_OP_NEGPROT is allowed.
2273 if (opcode != SMB2_OP_NEGPROT) {
2274 /* drop the connection */
2275 return NT_STATUS_INVALID_PARAMETER;
2280 * Check if the client provided a valid session id,
2281 * if so smbd_smb2_request_check_session() calls
2282 * set_current_user_info().
2284 * As some command don't require a valid session id
2285 * we defer the check of the session_status
2287 session_status = smbd_smb2_request_check_session(req);
2288 x = req->session;
2289 if (x != NULL) {
2290 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2291 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2292 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2295 req->do_signing = false;
2296 req->do_encryption = false;
2297 req->was_encrypted = false;
2298 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2299 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2300 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2302 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2303 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2304 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2305 (unsigned long long)x->global->session_wire_id,
2306 (unsigned long long)tf_session_id));
2308 * TODO: windows allows this...
2309 * should we drop the connection?
2311 * For now we just return ACCESS_DENIED
2312 * (Windows clients never trigger this)
2313 * and wait for an update of [MS-SMB2].
2315 return smbd_smb2_request_error(req,
2316 NT_STATUS_ACCESS_DENIED);
2319 req->was_encrypted = true;
2322 if (encryption_required && !req->was_encrypted) {
2323 return smbd_smb2_request_error(req,
2324 NT_STATUS_ACCESS_DENIED);
2327 call = smbd_smb2_call(opcode);
2328 if (call == NULL) {
2329 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2332 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2333 SMB2_HDR_FLAG_SIGNED |
2334 SMB2_HDR_FLAG_DFS;
2335 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2336 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2338 if (opcode == SMB2_OP_NEGPROT) {
2339 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2340 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2343 if (opcode == SMB2_OP_CANCEL) {
2344 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2346 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2347 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2349 if ((flags & ~allowed_flags) != 0) {
2350 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2353 if (flags & SMB2_HDR_FLAG_CHAINED) {
2355 * This check is mostly for giving the correct error code
2356 * for compounded requests.
2358 if (!NT_STATUS_IS_OK(session_status)) {
2359 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2361 } else {
2362 req->compat_chain_fsp = NULL;
2365 if (req->was_encrypted) {
2366 signing_required = false;
2367 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2368 DATA_BLOB signing_key = data_blob_null;
2370 if (x == NULL) {
2372 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2373 * If the SMB2 header of the SMB2 NEGOTIATE
2374 * request has the SMB2_FLAGS_SIGNED bit set in the
2375 * Flags field, the server MUST fail the request
2376 * with STATUS_INVALID_PARAMETER.
2378 * Microsoft test tool checks this.
2381 if ((opcode == SMB2_OP_NEGPROT) &&
2382 (flags & SMB2_HDR_FLAG_SIGNED)) {
2383 status = NT_STATUS_INVALID_PARAMETER;
2384 } else {
2385 status = NT_STATUS_USER_SESSION_DELETED;
2387 return smbd_smb2_request_error(req, status);
2390 signing_key = smbd_smb2_signing_key(x, xconn);
2393 * If we have a signing key, we should
2394 * sign the response
2396 if (signing_key.length > 0) {
2397 req->do_signing = true;
2400 status = smb2_signing_check_pdu(signing_key,
2401 xconn->protocol,
2402 SMBD_SMB2_IN_HDR_IOV(req),
2403 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2404 if (!NT_STATUS_IS_OK(status)) {
2405 return smbd_smb2_request_error(req, status);
2409 * Now that we know the request was correctly signed
2410 * we have to sign the response too.
2412 req->do_signing = true;
2414 if (!NT_STATUS_IS_OK(session_status)) {
2415 return smbd_smb2_request_error(req, session_status);
2417 } else if (opcode == SMB2_OP_CANCEL) {
2418 /* Cancel requests are allowed to skip the signing */
2419 } else if (signing_required) {
2421 * If signing is required we try to sign
2422 * a possible error response
2424 req->do_signing = true;
2425 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2428 if (flags & SMB2_HDR_FLAG_CHAINED) {
2429 req->compound_related = true;
2432 if (call->need_session) {
2433 if (!NT_STATUS_IS_OK(session_status)) {
2434 return smbd_smb2_request_error(req, session_status);
2438 if (call->need_tcon) {
2439 SMB_ASSERT(call->need_session);
2442 * This call needs to be run as user.
2444 * smbd_smb2_request_check_tcon()
2445 * calls change_to_user() on success.
2447 status = smbd_smb2_request_check_tcon(req);
2448 if (!NT_STATUS_IS_OK(status)) {
2449 return smbd_smb2_request_error(req, status);
2451 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2452 encryption_desired = true;
2454 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2455 encryption_required = true;
2457 if (encryption_required && !req->was_encrypted) {
2458 return smbd_smb2_request_error(req,
2459 NT_STATUS_ACCESS_DENIED);
2463 if (req->was_encrypted || encryption_desired) {
2464 req->do_encryption = true;
2467 if (req->session) {
2468 bool update_session_global = false;
2469 bool update_tcon_global = false;
2471 smb2srv_update_crypto_flags(req, opcode,
2472 &update_session_global,
2473 &update_tcon_global);
2475 if (update_session_global) {
2476 status = smbXsrv_session_update(x);
2477 if (!NT_STATUS_IS_OK(status)) {
2478 return smbd_smb2_request_error(req, status);
2481 if (update_tcon_global) {
2482 status = smbXsrv_tcon_update(req->tcon);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 return smbd_smb2_request_error(req, status);
2489 if (call->fileid_ofs != 0) {
2490 size_t needed = call->fileid_ofs + 16;
2491 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2492 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2493 uint64_t file_id_persistent;
2494 uint64_t file_id_volatile;
2495 struct files_struct *fsp;
2497 SMB_ASSERT(call->need_tcon);
2499 if (needed > body_size) {
2500 return smbd_smb2_request_error(req,
2501 NT_STATUS_INVALID_PARAMETER);
2504 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2505 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2507 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2508 if (fsp == NULL) {
2509 if (!call->allow_invalid_fileid) {
2510 return smbd_smb2_request_error(req,
2511 NT_STATUS_FILE_CLOSED);
2514 if (file_id_persistent != UINT64_MAX) {
2515 return smbd_smb2_request_error(req,
2516 NT_STATUS_FILE_CLOSED);
2518 if (file_id_volatile != UINT64_MAX) {
2519 return smbd_smb2_request_error(req,
2520 NT_STATUS_FILE_CLOSED);
2525 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 return smbd_smb2_request_error(req, status);
2530 if (call->as_root) {
2531 SMB_ASSERT(call->fileid_ofs == 0);
2532 /* This call needs to be run as root */
2533 change_to_root_user();
2534 } else {
2535 SMB_ASSERT(call->need_tcon);
2538 #define _INBYTES(_r) \
2539 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2541 switch (opcode) {
2542 case SMB2_OP_NEGPROT:
2543 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2544 req->profile, _INBYTES(req));
2545 return_value = smbd_smb2_request_process_negprot(req);
2546 break;
2548 case SMB2_OP_SESSSETUP:
2549 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2550 req->profile, _INBYTES(req));
2551 return_value = smbd_smb2_request_process_sesssetup(req);
2552 break;
2554 case SMB2_OP_LOGOFF:
2555 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2556 req->profile, _INBYTES(req));
2557 return_value = smbd_smb2_request_process_logoff(req);
2558 break;
2560 case SMB2_OP_TCON:
2561 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2562 req->profile, _INBYTES(req));
2563 return_value = smbd_smb2_request_process_tcon(req);
2564 break;
2566 case SMB2_OP_TDIS:
2567 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2568 req->profile, _INBYTES(req));
2569 return_value = smbd_smb2_request_process_tdis(req);
2570 break;
2572 case SMB2_OP_CREATE:
2573 if (req->subreq == NULL) {
2574 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2575 req->profile, _INBYTES(req));
2576 } else {
2577 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2579 return_value = smbd_smb2_request_process_create(req);
2580 break;
2582 case SMB2_OP_CLOSE:
2583 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2584 req->profile, _INBYTES(req));
2585 return_value = smbd_smb2_request_process_close(req);
2586 break;
2588 case SMB2_OP_FLUSH:
2589 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2590 req->profile, _INBYTES(req));
2591 return_value = smbd_smb2_request_process_flush(req);
2592 break;
2594 case SMB2_OP_READ:
2595 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2596 req->profile, _INBYTES(req));
2597 return_value = smbd_smb2_request_process_read(req);
2598 break;
2600 case SMB2_OP_WRITE:
2601 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2602 req->profile, _INBYTES(req));
2603 return_value = smbd_smb2_request_process_write(req);
2604 break;
2606 case SMB2_OP_LOCK:
2607 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2608 req->profile, _INBYTES(req));
2609 return_value = smbd_smb2_request_process_lock(req);
2610 break;
2612 case SMB2_OP_IOCTL:
2613 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2614 req->profile, _INBYTES(req));
2615 return_value = smbd_smb2_request_process_ioctl(req);
2616 break;
2618 case SMB2_OP_CANCEL:
2619 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2620 req->profile, _INBYTES(req));
2621 return_value = smbd_smb2_request_process_cancel(req);
2622 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2625 * We don't need the request anymore cancel requests never
2626 * have a response.
2628 * smbd_smb2_request_process_cancel() already called
2629 * DLIST_REMOVE(xconn->smb2.requests, req);
2631 TALLOC_FREE(req);
2633 break;
2635 case SMB2_OP_KEEPALIVE:
2636 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2637 req->profile, _INBYTES(req));
2638 return_value = smbd_smb2_request_process_keepalive(req);
2639 break;
2641 case SMB2_OP_QUERY_DIRECTORY:
2642 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2643 req->profile, _INBYTES(req));
2644 return_value = smbd_smb2_request_process_query_directory(req);
2645 break;
2647 case SMB2_OP_NOTIFY:
2648 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2649 req->profile, _INBYTES(req));
2650 return_value = smbd_smb2_request_process_notify(req);
2651 break;
2653 case SMB2_OP_GETINFO:
2654 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2655 req->profile, _INBYTES(req));
2656 return_value = smbd_smb2_request_process_getinfo(req);
2657 break;
2659 case SMB2_OP_SETINFO:
2660 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2661 req->profile, _INBYTES(req));
2662 return_value = smbd_smb2_request_process_setinfo(req);
2663 break;
2665 case SMB2_OP_BREAK:
2666 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2667 req->profile, _INBYTES(req));
2668 return_value = smbd_smb2_request_process_break(req);
2669 break;
2671 default:
2672 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2673 break;
2675 return return_value;
2678 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2680 struct smbXsrv_connection *xconn = req->xconn;
2681 const uint8_t *inhdr;
2682 uint16_t channel_sequence;
2683 struct smbXsrv_open *op;
2685 if (!req->request_counters_updated) {
2686 return;
2689 if (xconn->protocol < PROTOCOL_SMB2_22) {
2690 return;
2693 if (req->compat_chain_fsp == NULL) {
2694 return;
2697 op = req->compat_chain_fsp->op;
2698 if (op == NULL) {
2699 return;
2702 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2703 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2705 if (op->global->channel_sequence == channel_sequence) {
2706 SMB_ASSERT(op->request_count > 0);
2707 op->request_count -= 1;
2708 } else {
2709 SMB_ASSERT(op->pre_request_count > 0);
2710 op->pre_request_count -= 1;
2714 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2716 struct smbXsrv_connection *xconn = req->xconn;
2717 int first_idx = 1;
2718 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2719 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2720 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2721 NTSTATUS status;
2722 bool ok;
2724 req->subreq = NULL;
2725 TALLOC_FREE(req->async_te);
2727 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2728 smbd_smb2_request_reply_update_counts(req);
2730 if (req->do_encryption &&
2731 (firsttf->iov_len == 0) &&
2732 (req->first_key.length == 0) &&
2733 (req->session != NULL) &&
2734 (req->session->global->encryption_key.length != 0))
2736 DATA_BLOB encryption_key = req->session->global->encryption_key;
2737 uint8_t *tf;
2738 uint64_t session_id = req->session->global->session_wire_id;
2739 uint64_t nonce_high;
2740 uint64_t nonce_low;
2742 status = smb2_get_new_nonce(req->session,
2743 &nonce_high,
2744 &nonce_low);
2745 if (!NT_STATUS_IS_OK(status)) {
2746 return status;
2750 * We need to place the SMB2_TRANSFORM header before the
2751 * first SMB2 header
2755 * we need to remember the encryption key
2756 * and defer the signing/encryption until
2757 * we are sure that we do not change
2758 * the header again.
2760 req->first_key = data_blob_dup_talloc(req, encryption_key);
2761 if (req->first_key.data == NULL) {
2762 return NT_STATUS_NO_MEMORY;
2765 tf = talloc_zero_array(req, uint8_t,
2766 SMB2_TF_HDR_SIZE);
2767 if (tf == NULL) {
2768 return NT_STATUS_NO_MEMORY;
2771 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2772 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2773 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2774 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2776 firsttf->iov_base = (void *)tf;
2777 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2780 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2781 (req->last_key.length > 0) &&
2782 (firsttf->iov_len == 0))
2784 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2785 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2788 * As we are sure the header of the last request in the
2789 * compound chain will not change, we can to sign here
2790 * with the last signing key we remembered.
2792 status = smb2_signing_sign_pdu(req->last_key,
2793 xconn->protocol,
2794 lasthdr,
2795 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2796 if (!NT_STATUS_IS_OK(status)) {
2797 return status;
2800 if (req->last_key.length > 0) {
2801 data_blob_clear_free(&req->last_key);
2804 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2805 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2807 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2809 if (req->current_idx < req->out.vector_count) {
2811 * We must process the remaining compound
2812 * SMB2 requests before any new incoming SMB2
2813 * requests. This is because incoming SMB2
2814 * requests may include a cancel for a
2815 * compound request we haven't processed
2816 * yet.
2818 struct tevent_immediate *im = tevent_create_immediate(req);
2819 if (!im) {
2820 return NT_STATUS_NO_MEMORY;
2823 if (req->do_signing && firsttf->iov_len == 0) {
2824 struct smbXsrv_session *x = req->session;
2825 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2828 * we need to remember the signing key
2829 * and defer the signing until
2830 * we are sure that we do not change
2831 * the header again.
2833 req->last_key = data_blob_dup_talloc(req, signing_key);
2834 if (req->last_key.data == NULL) {
2835 return NT_STATUS_NO_MEMORY;
2839 tevent_schedule_immediate(im,
2840 req->sconn->ev_ctx,
2841 smbd_smb2_request_dispatch_immediate,
2842 req);
2843 return NT_STATUS_OK;
2846 if (req->compound_related) {
2847 req->compound_related = false;
2850 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2851 if (!ok) {
2852 return NT_STATUS_INVALID_PARAMETER_MIX;
2855 /* Set credit for these operations (zero credits if this
2856 is a final reply for an async operation). */
2857 smb2_calculate_credits(req, req);
2860 * now check if we need to sign the current response
2862 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2863 status = smb2_signing_encrypt_pdu(req->first_key,
2864 xconn->smb2.server.cipher,
2865 firsttf,
2866 req->out.vector_count - first_idx);
2867 if (!NT_STATUS_IS_OK(status)) {
2868 return status;
2870 } else if (req->do_signing) {
2871 struct smbXsrv_session *x = req->session;
2872 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2874 status = smb2_signing_sign_pdu(signing_key,
2875 xconn->protocol,
2876 outhdr,
2877 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2878 if (!NT_STATUS_IS_OK(status)) {
2879 return status;
2882 if (req->first_key.length > 0) {
2883 data_blob_clear_free(&req->first_key);
2886 if (req->preauth != NULL) {
2887 struct hc_sha512state sctx;
2888 int i;
2890 samba_SHA512_Init(&sctx);
2891 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2892 sizeof(req->preauth->sha512_value));
2893 for (i = 1; i < req->in.vector_count; i++) {
2894 samba_SHA512_Update(&sctx,
2895 req->in.vector[i].iov_base,
2896 req->in.vector[i].iov_len);
2898 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2900 samba_SHA512_Init(&sctx);
2901 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2902 sizeof(req->preauth->sha512_value));
2903 for (i = 1; i < req->out.vector_count; i++) {
2904 samba_SHA512_Update(&sctx,
2905 req->out.vector[i].iov_base,
2906 req->out.vector[i].iov_len);
2908 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2910 req->preauth = NULL;
2913 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2914 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2915 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2916 /* Dynamic part is NULL. Chop it off,
2917 We're going to send it via sendfile. */
2918 req->out.vector_count -= 1;
2922 * We're done with this request -
2923 * move it off the "being processed" queue.
2925 DLIST_REMOVE(xconn->smb2.requests, req);
2927 req->queue_entry.mem_ctx = req;
2928 req->queue_entry.vector = req->out.vector;
2929 req->queue_entry.count = req->out.vector_count;
2930 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2931 xconn->smb2.send_queue_len++;
2933 status = smbd_smb2_flush_send_queue(xconn);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 return status;
2938 return NT_STATUS_OK;
2941 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2943 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2944 struct tevent_immediate *im,
2945 void *private_data)
2947 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2948 struct smbd_smb2_request);
2949 struct smbXsrv_connection *xconn = req->xconn;
2950 NTSTATUS status;
2952 TALLOC_FREE(im);
2954 if (DEBUGLEVEL >= 10) {
2955 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2956 req->current_idx, req->in.vector_count));
2957 print_req_vectors(req);
2960 status = smbd_smb2_request_dispatch(req);
2961 if (!NT_STATUS_IS_OK(status)) {
2962 smbd_server_connection_terminate(xconn, nt_errstr(status));
2963 return;
2966 status = smbd_smb2_request_next_incoming(xconn);
2967 if (!NT_STATUS_IS_OK(status)) {
2968 smbd_server_connection_terminate(xconn, nt_errstr(status));
2969 return;
2973 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2974 NTSTATUS status,
2975 DATA_BLOB body, DATA_BLOB *dyn,
2976 const char *location)
2978 uint8_t *outhdr;
2979 struct iovec *outbody_v;
2980 struct iovec *outdyn_v;
2981 uint32_t next_command_ofs;
2983 DEBUG(10,("smbd_smb2_request_done_ex: "
2984 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2985 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2986 dyn ? "yes": "no",
2987 (unsigned int)(dyn ? dyn->length : 0),
2988 location));
2990 if (body.length < 2) {
2991 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2994 if ((body.length % 2) != 0) {
2995 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2998 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2999 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3000 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3002 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3003 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3005 outbody_v->iov_base = (void *)body.data;
3006 outbody_v->iov_len = body.length;
3008 if (dyn) {
3009 outdyn_v->iov_base = (void *)dyn->data;
3010 outdyn_v->iov_len = dyn->length;
3011 } else {
3012 outdyn_v->iov_base = NULL;
3013 outdyn_v->iov_len = 0;
3017 * See if we need to recalculate the offset to the next response
3019 * Note that all responses may require padding (including the very last
3020 * one).
3022 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3023 next_command_ofs = SMB2_HDR_BODY;
3024 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3025 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3028 if ((next_command_ofs % 8) != 0) {
3029 size_t pad_size = 8 - (next_command_ofs % 8);
3030 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3032 * if the dyn buffer is empty
3033 * we can use it to add padding
3035 uint8_t *pad;
3037 pad = talloc_zero_array(req,
3038 uint8_t, pad_size);
3039 if (pad == NULL) {
3040 return smbd_smb2_request_error(req,
3041 NT_STATUS_NO_MEMORY);
3044 outdyn_v->iov_base = (void *)pad;
3045 outdyn_v->iov_len = pad_size;
3046 } else {
3048 * For now we copy the dynamic buffer
3049 * and add the padding to the new buffer
3051 size_t old_size;
3052 uint8_t *old_dyn;
3053 size_t new_size;
3054 uint8_t *new_dyn;
3056 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3057 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3059 new_size = old_size + pad_size;
3060 new_dyn = talloc_zero_array(req,
3061 uint8_t, new_size);
3062 if (new_dyn == NULL) {
3063 return smbd_smb2_request_error(req,
3064 NT_STATUS_NO_MEMORY);
3067 memcpy(new_dyn, old_dyn, old_size);
3068 memset(new_dyn + old_size, 0, pad_size);
3070 outdyn_v->iov_base = (void *)new_dyn;
3071 outdyn_v->iov_len = new_size;
3073 next_command_ofs += pad_size;
3076 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3077 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3078 } else {
3079 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3081 return smbd_smb2_request_reply(req);
3084 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3085 NTSTATUS status,
3086 DATA_BLOB *info,
3087 const char *location)
3089 struct smbXsrv_connection *xconn = req->xconn;
3090 DATA_BLOB body;
3091 DATA_BLOB _dyn;
3092 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3093 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3095 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3096 "at %s\n", req->current_idx, nt_errstr(status),
3097 info ? " +info" : "", location);
3099 if (unread_bytes) {
3100 /* Recvfile error. Drain incoming socket. */
3101 size_t ret;
3103 errno = 0;
3104 ret = drain_socket(xconn->transport.sock, unread_bytes);
3105 if (ret != unread_bytes) {
3106 NTSTATUS error;
3108 if (errno == 0) {
3109 error = NT_STATUS_IO_DEVICE_ERROR;
3110 } else {
3111 error = map_nt_error_from_unix_common(errno);
3114 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3115 "ret[%u] errno[%d] => %s\n",
3116 (unsigned)unread_bytes,
3117 (unsigned)ret, errno, nt_errstr(error)));
3118 return error;
3122 body.data = outhdr + SMB2_HDR_BODY;
3123 body.length = 8;
3124 SSVAL(body.data, 0, 9);
3126 if (info) {
3127 SIVAL(body.data, 0x04, info->length);
3128 } else {
3129 /* Allocated size of req->out.vector[i].iov_base
3130 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3131 * 1 byte without having to do an alloc.
3133 info = &_dyn;
3134 info->data = ((uint8_t *)outhdr) +
3135 OUTVEC_ALLOC_SIZE - 1;
3136 info->length = 1;
3137 SCVAL(info->data, 0, 0);
3141 * Note: Even if there is an error, continue to process the request.
3142 * per MS-SMB2.
3145 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3149 struct smbd_smb2_send_break_state {
3150 struct smbd_smb2_send_queue queue_entry;
3151 uint8_t nbt_hdr[NBT_HDR_SIZE];
3152 uint8_t tf[SMB2_TF_HDR_SIZE];
3153 uint8_t hdr[SMB2_HDR_BODY];
3154 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3155 uint8_t body[1];
3158 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3159 struct smbXsrv_session *session,
3160 struct smbXsrv_tcon *tcon,
3161 const uint8_t *body,
3162 size_t body_len)
3164 struct smbd_smb2_send_break_state *state;
3165 bool do_encryption = false;
3166 uint64_t session_wire_id = 0;
3167 uint64_t nonce_high = 0;
3168 uint64_t nonce_low = 0;
3169 NTSTATUS status;
3170 size_t statelen;
3171 bool ok;
3173 if (session != NULL) {
3174 session_wire_id = session->global->session_wire_id;
3175 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3176 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3177 do_encryption = true;
3181 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3182 body_len;
3184 state = talloc_zero_size(xconn, statelen);
3185 if (state == NULL) {
3186 return NT_STATUS_NO_MEMORY;
3188 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3190 if (do_encryption) {
3191 status = smb2_get_new_nonce(session,
3192 &nonce_high,
3193 &nonce_low);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 return status;
3199 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3200 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3201 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3202 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3204 SIVAL(state->hdr, 0, SMB2_MAGIC);
3205 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3206 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3207 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3208 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3209 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3210 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3211 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3212 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3213 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3214 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3215 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3216 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3218 state->vector[0] = (struct iovec) {
3219 .iov_base = state->nbt_hdr,
3220 .iov_len = sizeof(state->nbt_hdr)
3223 if (do_encryption) {
3224 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3225 .iov_base = state->tf,
3226 .iov_len = sizeof(state->tf)
3228 } else {
3229 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3230 .iov_base = NULL,
3231 .iov_len = 0
3235 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3236 .iov_base = state->hdr,
3237 .iov_len = sizeof(state->hdr)
3240 memcpy(state->body, body, body_len);
3242 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3243 .iov_base = state->body,
3244 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3248 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3251 ok = smb2_setup_nbt_length(state->vector,
3252 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3253 if (!ok) {
3254 return NT_STATUS_INVALID_PARAMETER_MIX;
3257 if (do_encryption) {
3258 DATA_BLOB encryption_key = session->global->encryption_key;
3260 status = smb2_signing_encrypt_pdu(encryption_key,
3261 xconn->smb2.server.cipher,
3262 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3263 SMBD_SMB2_NUM_IOV_PER_REQ);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 return status;
3269 state->queue_entry.mem_ctx = state;
3270 state->queue_entry.vector = state->vector;
3271 state->queue_entry.count = ARRAY_SIZE(state->vector);
3272 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3273 xconn->smb2.send_queue_len++;
3275 status = smbd_smb2_flush_send_queue(xconn);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 return status;
3280 return NT_STATUS_OK;
3283 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3284 struct smbXsrv_session *session,
3285 struct smbXsrv_tcon *tcon,
3286 struct smbXsrv_open *op,
3287 uint8_t oplock_level)
3289 uint8_t body[0x18];
3291 SSVAL(body, 0x00, sizeof(body));
3292 SCVAL(body, 0x02, oplock_level);
3293 SCVAL(body, 0x03, 0); /* reserved */
3294 SIVAL(body, 0x04, 0); /* reserved */
3295 SBVAL(body, 0x08, op->global->open_persistent_id);
3296 SBVAL(body, 0x10, op->global->open_volatile_id);
3298 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3301 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3302 uint16_t new_epoch,
3303 uint32_t lease_flags,
3304 struct smb2_lease_key *lease_key,
3305 uint32_t current_lease_state,
3306 uint32_t new_lease_state)
3308 uint8_t body[0x2c];
3310 SSVAL(body, 0x00, sizeof(body));
3311 SSVAL(body, 0x02, new_epoch);
3312 SIVAL(body, 0x04, lease_flags);
3313 SBVAL(body, 0x08, lease_key->data[0]);
3314 SBVAL(body, 0x10, lease_key->data[1]);
3315 SIVAL(body, 0x18, current_lease_state);
3316 SIVAL(body, 0x1c, new_lease_state);
3317 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3318 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3319 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3321 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3324 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3326 NTSTATUS status;
3327 uint32_t flags;
3328 uint64_t file_id_persistent;
3329 uint64_t file_id_volatile;
3330 struct smbXsrv_open *op = NULL;
3331 struct files_struct *fsp = NULL;
3332 const uint8_t *body = NULL;
3335 * This is only called with a pktbuf
3336 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3337 * bytes
3340 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3341 /* Transform header. Cannot recvfile. */
3342 return false;
3344 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3345 /* Not SMB2. Normal error path will cope. */
3346 return false;
3348 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3349 /* Not SMB2. Normal error path will cope. */
3350 return false;
3352 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3353 /* Needs to be a WRITE. */
3354 return false;
3356 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3357 /* Chained. Cannot recvfile. */
3358 return false;
3360 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3361 if (flags & SMB2_HDR_FLAG_CHAINED) {
3362 /* Chained. Cannot recvfile. */
3363 return false;
3365 if (flags & SMB2_HDR_FLAG_SIGNED) {
3366 /* Signed. Cannot recvfile. */
3367 return false;
3370 body = &state->pktbuf[SMB2_HDR_BODY];
3372 file_id_persistent = BVAL(body, 0x10);
3373 file_id_volatile = BVAL(body, 0x18);
3375 status = smb2srv_open_lookup(state->req->xconn,
3376 file_id_persistent,
3377 file_id_volatile,
3378 0, /* now */
3379 &op);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 return false;
3384 fsp = op->compat;
3385 if (fsp == NULL) {
3386 return false;
3388 if (fsp->conn == NULL) {
3389 return false;
3392 if (IS_IPC(fsp->conn)) {
3393 return false;
3395 if (IS_PRINT(fsp->conn)) {
3396 return false;
3399 DEBUG(10,("Doing recvfile write len = %u\n",
3400 (unsigned int)(state->pktfull - state->pktlen)));
3402 return true;
3405 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3407 struct smbd_server_connection *sconn = xconn->client->sconn;
3408 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3409 size_t max_send_queue_len;
3410 size_t cur_send_queue_len;
3412 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3414 * we're not supposed to do any io
3416 return NT_STATUS_OK;
3419 if (state->req != NULL) {
3421 * if there is already a tstream_readv_pdu
3422 * pending, we are done.
3424 return NT_STATUS_OK;
3427 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3428 cur_send_queue_len = xconn->smb2.send_queue_len;
3430 if (cur_send_queue_len > max_send_queue_len) {
3432 * if we have a lot of requests to send,
3433 * we wait until they are on the wire until we
3434 * ask for the next request.
3436 return NT_STATUS_OK;
3439 /* ask for the next request */
3440 ZERO_STRUCTP(state);
3441 state->req = smbd_smb2_request_allocate(xconn);
3442 if (state->req == NULL) {
3443 return NT_STATUS_NO_MEMORY;
3445 state->req->sconn = sconn;
3446 state->req->xconn = xconn;
3447 state->min_recv_size = lp_min_receive_file_size();
3449 TEVENT_FD_READABLE(xconn->transport.fde);
3451 return NT_STATUS_OK;
3454 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3455 uint64_t expected_seq_low,
3456 const uint8_t *inpdu, size_t size)
3458 struct smbd_server_connection *sconn = xconn->client->sconn;
3459 NTSTATUS status;
3460 struct smbd_smb2_request *req = NULL;
3462 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3463 (unsigned int)size));
3465 status = smbd_initialize_smb2(xconn, expected_seq_low);
3466 if (!NT_STATUS_IS_OK(status)) {
3467 smbd_server_connection_terminate(xconn, nt_errstr(status));
3468 return;
3471 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3472 if (!NT_STATUS_IS_OK(status)) {
3473 smbd_server_connection_terminate(xconn, nt_errstr(status));
3474 return;
3477 status = smbd_smb2_request_validate(req);
3478 if (!NT_STATUS_IS_OK(status)) {
3479 smbd_server_connection_terminate(xconn, nt_errstr(status));
3480 return;
3483 status = smbd_smb2_request_setup_out(req);
3484 if (!NT_STATUS_IS_OK(status)) {
3485 smbd_server_connection_terminate(xconn, nt_errstr(status));
3486 return;
3489 #ifdef WITH_PROFILE
3491 * this was already counted at the SMB1 layer =>
3492 * smbd_smb2_request_dispatch() should not count it twice.
3494 if (profile_p->values.request_stats.count > 0) {
3495 profile_p->values.request_stats.count--;
3497 #endif
3498 status = smbd_smb2_request_dispatch(req);
3499 if (!NT_STATUS_IS_OK(status)) {
3500 smbd_server_connection_terminate(xconn, nt_errstr(status));
3501 return;
3504 status = smbd_smb2_request_next_incoming(xconn);
3505 if (!NT_STATUS_IS_OK(status)) {
3506 smbd_server_connection_terminate(xconn, nt_errstr(status));
3507 return;
3510 sconn->num_requests++;
3513 static int socket_error_from_errno(int ret,
3514 int sys_errno,
3515 bool *retry)
3517 *retry = false;
3519 if (ret >= 0) {
3520 return 0;
3523 if (ret != -1) {
3524 return EIO;
3527 if (sys_errno == 0) {
3528 return EIO;
3531 if (sys_errno == EINTR) {
3532 *retry = true;
3533 return sys_errno;
3536 if (sys_errno == EINPROGRESS) {
3537 *retry = true;
3538 return sys_errno;
3541 if (sys_errno == EAGAIN) {
3542 *retry = true;
3543 return sys_errno;
3546 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3547 if (sys_errno == ENOMEM) {
3548 *retry = true;
3549 return sys_errno;
3552 #ifdef EWOULDBLOCK
3553 #if EWOULDBLOCK != EAGAIN
3554 if (sys_errno == EWOULDBLOCK) {
3555 *retry = true;
3556 return sys_errno;
3558 #endif
3559 #endif
3561 return sys_errno;
3564 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3566 int ret;
3567 int err;
3568 bool retry;
3570 if (xconn->smb2.send_queue == NULL) {
3571 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3572 return NT_STATUS_OK;
3575 while (xconn->smb2.send_queue != NULL) {
3576 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3577 bool ok;
3579 if (e->sendfile_header != NULL) {
3580 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3581 size_t size = 0;
3582 size_t i = 0;
3583 uint8_t *buf;
3585 for (i=0; i < e->count; i++) {
3586 size += e->vector[i].iov_len;
3589 if (size <= e->sendfile_header->length) {
3590 buf = e->sendfile_header->data;
3591 } else {
3592 buf = talloc_array(e->mem_ctx, uint8_t, size);
3593 if (buf == NULL) {
3594 return NT_STATUS_NO_MEMORY;
3598 size = 0;
3599 for (i=0; i < e->count; i++) {
3600 memcpy(buf+size,
3601 e->vector[i].iov_base,
3602 e->vector[i].iov_len);
3603 size += e->vector[i].iov_len;
3606 e->sendfile_header->data = buf;
3607 e->sendfile_header->length = size;
3608 e->sendfile_status = &status;
3609 e->count = 0;
3611 xconn->smb2.send_queue_len--;
3612 DLIST_REMOVE(xconn->smb2.send_queue, e);
3614 * This triggers the sendfile path via
3615 * the destructor.
3617 talloc_free(e->mem_ctx);
3619 if (!NT_STATUS_IS_OK(status)) {
3620 return status;
3622 continue;
3625 ret = writev(xconn->transport.sock, e->vector, e->count);
3626 if (ret == 0) {
3627 /* propagate end of file */
3628 return NT_STATUS_INTERNAL_ERROR;
3630 err = socket_error_from_errno(ret, errno, &retry);
3631 if (retry) {
3632 /* retry later */
3633 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3634 return NT_STATUS_OK;
3636 if (err != 0) {
3637 return map_nt_error_from_unix_common(err);
3640 ok = iov_advance(&e->vector, &e->count, ret);
3641 if (!ok) {
3642 return NT_STATUS_INTERNAL_ERROR;
3645 if (e->count > 0) {
3646 /* we have more to write */
3647 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3648 return NT_STATUS_OK;
3651 xconn->smb2.send_queue_len--;
3652 DLIST_REMOVE(xconn->smb2.send_queue, e);
3653 talloc_free(e->mem_ctx);
3656 return NT_STATUS_OK;
3659 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3660 uint16_t fde_flags)
3662 struct smbd_server_connection *sconn = xconn->client->sconn;
3663 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3664 struct smbd_smb2_request *req = NULL;
3665 size_t min_recvfile_size = UINT32_MAX;
3666 int ret;
3667 int err;
3668 bool retry;
3669 NTSTATUS status;
3670 NTTIME now;
3672 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3674 * we're not supposed to do any io
3676 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3677 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3678 return NT_STATUS_OK;
3681 if (fde_flags & TEVENT_FD_WRITE) {
3682 status = smbd_smb2_flush_send_queue(xconn);
3683 if (!NT_STATUS_IS_OK(status)) {
3684 return status;
3688 if (!(fde_flags & TEVENT_FD_READ)) {
3689 return NT_STATUS_OK;
3692 if (state->req == NULL) {
3693 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3694 return NT_STATUS_OK;
3697 again:
3698 if (!state->hdr.done) {
3699 state->hdr.done = true;
3701 state->vector.iov_base = (void *)state->hdr.nbt;
3702 state->vector.iov_len = NBT_HDR_SIZE;
3705 ret = readv(xconn->transport.sock, &state->vector, 1);
3706 if (ret == 0) {
3707 /* propagate end of file */
3708 return NT_STATUS_END_OF_FILE;
3710 err = socket_error_from_errno(ret, errno, &retry);
3711 if (retry) {
3712 /* retry later */
3713 TEVENT_FD_READABLE(xconn->transport.fde);
3714 return NT_STATUS_OK;
3716 if (err != 0) {
3717 return map_nt_error_from_unix_common(err);
3720 if (ret < state->vector.iov_len) {
3721 uint8_t *base;
3722 base = (uint8_t *)state->vector.iov_base;
3723 base += ret;
3724 state->vector.iov_base = (void *)base;
3725 state->vector.iov_len -= ret;
3726 /* we have more to read */
3727 TEVENT_FD_READABLE(xconn->transport.fde);
3728 return NT_STATUS_OK;
3731 if (state->pktlen > 0) {
3732 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3734 * Not a possible receivefile write.
3735 * Read the rest of the data.
3737 state->doing_receivefile = false;
3739 state->pktbuf = talloc_realloc(state->req,
3740 state->pktbuf,
3741 uint8_t,
3742 state->pktfull);
3743 if (state->pktbuf == NULL) {
3744 return NT_STATUS_NO_MEMORY;
3747 state->vector.iov_base = (void *)(state->pktbuf +
3748 state->pktlen);
3749 state->vector.iov_len = (state->pktfull -
3750 state->pktlen);
3752 state->pktlen = state->pktfull;
3753 goto again;
3757 * Either this is a receivefile write so we've
3758 * done a short read, or if not we have all the data.
3760 goto got_full;
3764 * Now we analyze the NBT header
3766 if (state->hdr.nbt[0] != 0x00) {
3767 state->min_recv_size = 0;
3769 state->pktfull = smb2_len(state->hdr.nbt);
3770 if (state->pktfull == 0) {
3771 goto got_full;
3774 if (state->min_recv_size != 0) {
3775 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3776 min_recvfile_size += state->min_recv_size;
3779 if (state->pktfull > min_recvfile_size) {
3781 * Might be a receivefile write. Read the SMB2 HEADER +
3782 * SMB2_WRITE header first. Set 'doing_receivefile'
3783 * as we're *attempting* receivefile write. If this
3784 * turns out not to be a SMB2_WRITE request or otherwise
3785 * not suitable then we'll just read the rest of the data
3786 * the next time this function is called.
3788 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3789 state->doing_receivefile = true;
3790 } else {
3791 state->pktlen = state->pktfull;
3794 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3795 if (state->pktbuf == NULL) {
3796 return NT_STATUS_NO_MEMORY;
3799 state->vector.iov_base = (void *)state->pktbuf;
3800 state->vector.iov_len = state->pktlen;
3802 goto again;
3804 got_full:
3806 if (state->hdr.nbt[0] != 0x00) {
3807 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3808 state->hdr.nbt[0]));
3810 req = state->req;
3811 ZERO_STRUCTP(state);
3812 state->req = req;
3813 state->min_recv_size = lp_min_receive_file_size();
3814 req = NULL;
3815 goto again;
3818 req = state->req;
3819 state->req = NULL;
3821 req->request_time = timeval_current();
3822 now = timeval_to_nttime(&req->request_time);
3824 status = smbd_smb2_inbuf_parse_compound(xconn,
3825 now,
3826 state->pktbuf,
3827 state->pktlen,
3828 req,
3829 &req->in.vector,
3830 &req->in.vector_count);
3831 if (!NT_STATUS_IS_OK(status)) {
3832 return status;
3835 if (state->doing_receivefile) {
3836 req->smb1req = talloc_zero(req, struct smb_request);
3837 if (req->smb1req == NULL) {
3838 return NT_STATUS_NO_MEMORY;
3840 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3843 ZERO_STRUCTP(state);
3845 req->current_idx = 1;
3847 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3848 req->current_idx, req->in.vector_count));
3850 status = smbd_smb2_request_validate(req);
3851 if (!NT_STATUS_IS_OK(status)) {
3852 return status;
3855 status = smbd_smb2_request_setup_out(req);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 return status;
3860 status = smbd_smb2_request_dispatch(req);
3861 if (!NT_STATUS_IS_OK(status)) {
3862 return status;
3865 sconn->num_requests++;
3867 /* The timeout_processing function isn't run nearly
3868 often enough to implement 'max log size' without
3869 overrunning the size of the file by many megabytes.
3870 This is especially true if we are running at debug
3871 level 10. Checking every 50 SMB2s is a nice
3872 tradeoff of performance vs log file size overrun. */
3874 if ((sconn->num_requests % 50) == 0 &&
3875 need_to_check_log_size()) {
3876 change_to_root_user();
3877 check_log_size();
3880 status = smbd_smb2_request_next_incoming(xconn);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 return status;
3885 return NT_STATUS_OK;
3888 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3889 struct tevent_fd *fde,
3890 uint16_t flags,
3891 void *private_data)
3893 struct smbXsrv_connection *xconn =
3894 talloc_get_type_abort(private_data,
3895 struct smbXsrv_connection);
3896 NTSTATUS status;
3898 status = smbd_smb2_io_handler(xconn, flags);
3899 if (!NT_STATUS_IS_OK(status)) {
3900 smbd_server_connection_terminate(xconn, nt_errstr(status));
3901 return;