winbindd: queryuser - only get group name if needed
[Samba.git] / source3 / smbd / smb2_server.c
blobd95631f2ff4d56407f0a59450ea28bcdceb6ede9
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 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
276 bool async_internal)
278 req->async_internal = async_internal;
281 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
283 TALLOC_CTX *mem_pool;
284 struct smbd_smb2_request *req;
286 #if 0
287 /* Enable this to find subtle valgrind errors. */
288 mem_pool = talloc_init("smbd_smb2_request_allocate");
289 #else
290 mem_pool = talloc_tos();
291 #endif
292 if (mem_pool == NULL) {
293 return NULL;
296 req = talloc_zero(mem_pool, struct smbd_smb2_request);
297 if (req == NULL) {
298 talloc_free(mem_pool);
299 return NULL;
301 talloc_reparent(mem_pool, mem_ctx, req);
302 #if 0
303 TALLOC_FREE(mem_pool);
304 #endif
306 req->last_session_id = UINT64_MAX;
307 req->last_tid = UINT32_MAX;
309 talloc_set_destructor(req, smbd_smb2_request_destructor);
311 return req;
314 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
315 NTTIME now,
316 uint8_t *buf,
317 size_t buflen,
318 struct smbd_smb2_request *req,
319 struct iovec **piov,
320 int *pnum_iov)
322 TALLOC_CTX *mem_ctx = req;
323 struct iovec *iov;
324 int num_iov = 1;
325 size_t taken = 0;
326 uint8_t *first_hdr = buf;
327 size_t verified_buflen = 0;
328 uint8_t *tf = NULL;
329 size_t tf_len = 0;
332 * Note: index '0' is reserved for the transport protocol
334 iov = req->in._vector;
336 while (taken < buflen) {
337 size_t len = buflen - taken;
338 uint8_t *hdr = first_hdr + taken;
339 struct iovec *cur;
340 size_t full_size;
341 size_t next_command_ofs;
342 uint16_t body_size;
343 uint8_t *body = NULL;
344 uint32_t dyn_size;
345 uint8_t *dyn = NULL;
346 struct iovec *iov_alloc = NULL;
348 if (iov != req->in._vector) {
349 iov_alloc = iov;
352 if (verified_buflen > taken) {
353 len = verified_buflen - taken;
354 } else {
355 tf = NULL;
356 tf_len = 0;
359 if (len < 4) {
360 DEBUG(10, ("%d bytes left, expected at least %d\n",
361 (int)len, 4));
362 goto inval;
364 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
365 struct smbXsrv_session *s = NULL;
366 uint64_t uid;
367 struct iovec tf_iov[2];
368 NTSTATUS status;
369 size_t enc_len;
371 if (xconn->protocol < PROTOCOL_SMB2_24) {
372 DEBUG(10, ("Got SMB2_TRANSFORM header, "
373 "but dialect[0x%04X] is used\n",
374 xconn->smb2.server.dialect));
375 goto inval;
378 if (xconn->smb2.server.cipher == 0) {
379 DEBUG(10, ("Got SMB2_TRANSFORM header, "
380 "but not negotiated "
381 "client[0x%08X] server[0x%08X]\n",
382 xconn->smb2.client.capabilities,
383 xconn->smb2.server.capabilities));
384 goto inval;
387 if (len < SMB2_TF_HDR_SIZE) {
388 DEBUG(1, ("%d bytes left, expected at least %d\n",
389 (int)len, SMB2_TF_HDR_SIZE));
390 goto inval;
392 tf = hdr;
393 tf_len = SMB2_TF_HDR_SIZE;
394 taken += tf_len;
396 hdr = first_hdr + taken;
397 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
398 uid = BVAL(tf, SMB2_TF_SESSION_ID);
400 if (len < SMB2_TF_HDR_SIZE + enc_len) {
401 DEBUG(1, ("%d bytes left, expected at least %d\n",
402 (int)len,
403 (int)(SMB2_TF_HDR_SIZE + enc_len)));
404 goto inval;
407 status = smb2srv_session_lookup_conn(xconn, uid, now,
408 &s);
409 if (s == NULL) {
410 DEBUG(1, ("invalid session[%llu] in "
411 "SMB2_TRANSFORM header\n",
412 (unsigned long long)uid));
413 TALLOC_FREE(iov_alloc);
414 return NT_STATUS_USER_SESSION_DELETED;
417 tf_iov[0].iov_base = (void *)tf;
418 tf_iov[0].iov_len = tf_len;
419 tf_iov[1].iov_base = (void *)hdr;
420 tf_iov[1].iov_len = enc_len;
422 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
423 xconn->smb2.server.cipher,
424 tf_iov, 2);
425 if (!NT_STATUS_IS_OK(status)) {
426 TALLOC_FREE(iov_alloc);
427 return status;
430 verified_buflen = taken + enc_len;
431 len = enc_len;
435 * We need the header plus the body length field
438 if (len < SMB2_HDR_BODY + 2) {
439 DEBUG(10, ("%d bytes left, expected at least %d\n",
440 (int)len, SMB2_HDR_BODY));
441 goto inval;
443 if (IVAL(hdr, 0) != SMB2_MAGIC) {
444 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
445 IVAL(hdr, 0)));
446 goto inval;
448 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
449 DEBUG(10, ("Got HDR len %d, expected %d\n",
450 SVAL(hdr, 4), SMB2_HDR_BODY));
451 goto inval;
454 full_size = len;
455 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
456 body_size = SVAL(hdr, SMB2_HDR_BODY);
458 if (next_command_ofs != 0) {
459 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
460 goto inval;
462 if (next_command_ofs > full_size) {
463 goto inval;
465 full_size = next_command_ofs;
467 if (body_size < 2) {
468 goto inval;
470 body_size &= 0xfffe;
472 if (body_size > (full_size - SMB2_HDR_BODY)) {
474 * let the caller handle the error
476 body_size = full_size - SMB2_HDR_BODY;
478 body = hdr + SMB2_HDR_BODY;
479 dyn = body + body_size;
480 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
482 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
483 struct iovec *iov_tmp = NULL;
485 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
486 struct iovec,
487 num_iov +
488 SMBD_SMB2_NUM_IOV_PER_REQ);
489 if (iov_tmp == NULL) {
490 TALLOC_FREE(iov_alloc);
491 return NT_STATUS_NO_MEMORY;
494 if (iov_alloc == NULL) {
495 memcpy(iov_tmp,
496 req->in._vector,
497 sizeof(req->in._vector));
500 iov = iov_tmp;
502 cur = &iov[num_iov];
503 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
505 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
506 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
507 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
508 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
509 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
510 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
511 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
512 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
514 taken += full_size;
517 *piov = iov;
518 *pnum_iov = num_iov;
519 return NT_STATUS_OK;
521 inval:
522 if (iov != req->in._vector) {
523 TALLOC_FREE(iov);
525 return NT_STATUS_INVALID_PARAMETER;
528 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
529 const uint8_t *_inpdu, size_t size,
530 struct smbd_smb2_request **_req)
532 struct smbd_server_connection *sconn = xconn->client->sconn;
533 struct smbd_smb2_request *req;
534 uint32_t protocol_version;
535 uint8_t *inpdu = NULL;
536 const uint8_t *inhdr = NULL;
537 uint16_t cmd;
538 uint32_t next_command_ofs;
539 NTSTATUS status;
540 NTTIME now;
542 if (size < (SMB2_HDR_BODY + 2)) {
543 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
544 return NT_STATUS_INVALID_PARAMETER;
547 inhdr = _inpdu;
549 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
550 if (protocol_version != SMB2_MAGIC) {
551 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
552 protocol_version));
553 return NT_STATUS_INVALID_PARAMETER;
556 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
557 if (cmd != SMB2_OP_NEGPROT) {
558 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
559 cmd));
560 return NT_STATUS_INVALID_PARAMETER;
563 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
564 if (next_command_ofs != 0) {
565 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
566 next_command_ofs));
567 return NT_STATUS_INVALID_PARAMETER;
570 req = smbd_smb2_request_allocate(xconn);
571 if (req == NULL) {
572 return NT_STATUS_NO_MEMORY;
574 req->sconn = sconn;
575 req->xconn = xconn;
577 inpdu = talloc_memdup(req, _inpdu, size);
578 if (inpdu == NULL) {
579 return NT_STATUS_NO_MEMORY;
582 req->request_time = timeval_current();
583 now = timeval_to_nttime(&req->request_time);
585 status = smbd_smb2_inbuf_parse_compound(xconn,
586 now,
587 inpdu,
588 size,
589 req, &req->in.vector,
590 &req->in.vector_count);
591 if (!NT_STATUS_IS_OK(status)) {
592 TALLOC_FREE(req);
593 return status;
596 req->current_idx = 1;
598 *_req = req;
599 return NT_STATUS_OK;
602 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
603 uint64_t message_id, uint64_t seq_id)
605 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
606 unsigned int offset;
607 uint64_t seq_tmp;
609 seq_tmp = xconn->smb2.credits.seq_low;
610 if (seq_id < seq_tmp) {
611 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
612 "%llu (sequence id %llu) "
613 "(granted = %u, low = %llu, range = %u)\n",
614 (unsigned long long)message_id,
615 (unsigned long long)seq_id,
616 (unsigned int)xconn->smb2.credits.granted,
617 (unsigned long long)xconn->smb2.credits.seq_low,
618 (unsigned int)xconn->smb2.credits.seq_range));
619 return false;
622 seq_tmp += xconn->smb2.credits.seq_range;
623 if (seq_id >= seq_tmp) {
624 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
625 "%llu (sequence id %llu) "
626 "(granted = %u, low = %llu, range = %u)\n",
627 (unsigned long long)message_id,
628 (unsigned long long)seq_id,
629 (unsigned int)xconn->smb2.credits.granted,
630 (unsigned long long)xconn->smb2.credits.seq_low,
631 (unsigned int)xconn->smb2.credits.seq_range));
632 return false;
635 offset = seq_id % xconn->smb2.credits.max;
637 if (bitmap_query(credits_bm, offset)) {
638 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
639 "%llu (sequence id %llu) "
640 "(granted = %u, low = %llu, range = %u) "
641 "(bm offset %u)\n",
642 (unsigned long long)message_id,
643 (unsigned long long)seq_id,
644 (unsigned int)xconn->smb2.credits.granted,
645 (unsigned long long)xconn->smb2.credits.seq_low,
646 (unsigned int)xconn->smb2.credits.seq_range,
647 offset));
648 return false;
651 /* Mark the message_ids as seen in the bitmap. */
652 bitmap_set(credits_bm, offset);
654 if (seq_id != xconn->smb2.credits.seq_low) {
655 return true;
659 * Move the window forward by all the message_id's
660 * already seen.
662 while (bitmap_query(credits_bm, offset)) {
663 DEBUG(10,("smb2_validate_sequence_number: clearing "
664 "id %llu (position %u) from bitmap\n",
665 (unsigned long long)(xconn->smb2.credits.seq_low),
666 offset));
667 bitmap_clear(credits_bm, offset);
669 xconn->smb2.credits.seq_low += 1;
670 xconn->smb2.credits.seq_range -= 1;
671 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
674 return true;
677 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
678 const uint8_t *inhdr)
680 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
681 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
682 uint16_t credit_charge = 1;
683 uint64_t i;
685 if (opcode == SMB2_OP_CANCEL) {
686 /* SMB2_CANCEL requests by definition resend messageids. */
687 return true;
690 if (xconn->smb2.credits.multicredit) {
691 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
692 credit_charge = MAX(credit_charge, 1);
695 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
696 "credits_granted %llu, "
697 "seqnum low/range: %llu/%llu\n",
698 (unsigned long long) message_id,
699 (unsigned long long) credit_charge,
700 (unsigned long long) xconn->smb2.credits.granted,
701 (unsigned long long) xconn->smb2.credits.seq_low,
702 (unsigned long long) xconn->smb2.credits.seq_range));
704 if (xconn->smb2.credits.granted < credit_charge) {
705 DEBUG(0, ("smb2_validate_message_id: client used more "
706 "credits than granted, mid %llu, charge %llu, "
707 "credits_granted %llu, "
708 "seqnum low/range: %llu/%llu\n",
709 (unsigned long long) message_id,
710 (unsigned long long) credit_charge,
711 (unsigned long long) xconn->smb2.credits.granted,
712 (unsigned long long) xconn->smb2.credits.seq_low,
713 (unsigned long long) xconn->smb2.credits.seq_range));
714 return false;
718 * now check the message ids
720 * for multi-credit requests we need to check all current mid plus
721 * the implicit mids caused by the credit charge
722 * e.g. current mid = 15, charge 5 => mark 15-19 as used
725 for (i = 0; i <= (credit_charge-1); i++) {
726 uint64_t id = message_id + i;
727 bool ok;
729 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
730 (unsigned long long)message_id,
731 credit_charge,
732 (unsigned long long)id));
734 ok = smb2_validate_sequence_number(xconn, message_id, id);
735 if (!ok) {
736 return false;
740 /* substract used credits */
741 xconn->smb2.credits.granted -= credit_charge;
743 return true;
746 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
748 int count;
749 int idx;
751 count = req->in.vector_count;
753 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
754 /* It's not a SMB2 request */
755 return NT_STATUS_INVALID_PARAMETER;
758 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
759 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
760 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
761 const uint8_t *inhdr = NULL;
763 if (hdr->iov_len != SMB2_HDR_BODY) {
764 return NT_STATUS_INVALID_PARAMETER;
767 if (body->iov_len < 2) {
768 return NT_STATUS_INVALID_PARAMETER;
771 inhdr = (const uint8_t *)hdr->iov_base;
773 /* Check the SMB2 header */
774 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
775 return NT_STATUS_INVALID_PARAMETER;
778 if (!smb2_validate_message_id(req->xconn, inhdr)) {
779 return NT_STATUS_INVALID_PARAMETER;
783 return NT_STATUS_OK;
786 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
787 const struct iovec *in_vector,
788 struct iovec *out_vector)
790 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
791 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
792 uint16_t credit_charge = 1;
793 uint16_t credits_requested;
794 uint32_t out_flags;
795 uint16_t cmd;
796 NTSTATUS out_status;
797 uint16_t credits_granted = 0;
798 uint64_t credits_possible;
799 uint16_t current_max_credits;
802 * first we grant only 1/16th of the max range.
804 * Windows also starts with the 1/16th and then grants
805 * more later. I was only able to trigger higher
806 * values, when using a very high credit charge.
808 * TODO: scale up depending on load, free memory
809 * or other stuff.
810 * Maybe also on the relationship between number
811 * of requests and the used sequence number.
812 * Which means we would grant more credits
813 * for client which use multi credit requests.
815 current_max_credits = xconn->smb2.credits.max / 16;
816 current_max_credits = MAX(current_max_credits, 1);
818 if (xconn->smb2.credits.multicredit) {
819 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
820 credit_charge = MAX(credit_charge, 1);
823 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
824 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
825 credits_requested = MAX(credits_requested, 1);
826 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
827 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
829 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
831 if (xconn->smb2.credits.max < credit_charge) {
832 smbd_server_connection_terminate(xconn,
833 "client error: credit charge > max credits\n");
834 return;
837 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
839 * In case we already send an async interim
840 * response, we should not grant
841 * credits on the final response.
843 credits_granted = 0;
844 } else {
845 uint16_t additional_possible =
846 xconn->smb2.credits.max - credit_charge;
847 uint16_t additional_max = 0;
848 uint16_t additional_credits = credits_requested - 1;
850 switch (cmd) {
851 case SMB2_OP_NEGPROT:
852 break;
853 case SMB2_OP_SESSSETUP:
855 * Windows 2012 RC1 starts to grant
856 * additional credits
857 * with a successful session setup
859 if (NT_STATUS_IS_OK(out_status)) {
860 additional_max = 32;
862 break;
863 default:
865 * We match windows and only grant additional credits
866 * in chunks of 32.
868 additional_max = 32;
869 break;
872 additional_max = MIN(additional_max, additional_possible);
873 additional_credits = MIN(additional_credits, additional_max);
875 credits_granted = credit_charge + additional_credits;
879 * sequence numbers should not wrap
881 * 1. calculate the possible credits until
882 * the sequence numbers start to wrap on 64-bit.
884 * 2. UINT64_MAX is used for Break Notifications.
886 * 2. truncate the possible credits to the maximum
887 * credits we want to grant to the client in total.
889 * 3. remove the range we'll already granted to the client
890 * this makes sure the client consumes the lowest sequence
891 * number, before we can grant additional credits.
893 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
894 if (credits_possible > 0) {
895 /* remove UINT64_MAX */
896 credits_possible -= 1;
898 credits_possible = MIN(credits_possible, current_max_credits);
899 credits_possible -= xconn->smb2.credits.seq_range;
901 credits_granted = MIN(credits_granted, credits_possible);
903 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
904 xconn->smb2.credits.granted += credits_granted;
905 xconn->smb2.credits.seq_range += credits_granted;
907 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
908 "granted %u, current possible/max %u/%u, "
909 "total granted/max/low/range %u/%u/%llu/%u\n",
910 (unsigned int)credits_requested,
911 (unsigned int)credit_charge,
912 (unsigned int)credits_granted,
913 (unsigned int)credits_possible,
914 (unsigned int)current_max_credits,
915 (unsigned int)xconn->smb2.credits.granted,
916 (unsigned int)xconn->smb2.credits.max,
917 (unsigned long long)xconn->smb2.credits.seq_low,
918 (unsigned int)xconn->smb2.credits.seq_range));
921 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
922 struct smbd_smb2_request *outreq)
924 int count, idx;
925 uint16_t total_credits = 0;
927 count = outreq->out.vector_count;
929 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
930 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
931 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
932 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
934 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
936 /* To match Windows, count up what we
937 just granted. */
938 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
939 /* Set to zero in all but the last reply. */
940 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
941 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
942 } else {
943 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
948 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
950 if (req->current_idx <= 1) {
951 if (size <= sizeof(req->out._body)) {
952 return data_blob_const(req->out._body, size);
956 return data_blob_talloc(req, NULL, size);
959 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
961 struct smbXsrv_connection *xconn = req->xconn;
962 TALLOC_CTX *mem_ctx;
963 struct iovec *vector;
964 int count;
965 int idx;
966 bool ok;
968 count = req->in.vector_count;
969 if (count <= ARRAY_SIZE(req->out._vector)) {
970 mem_ctx = req;
971 vector = req->out._vector;
972 } else {
973 vector = talloc_zero_array(req, struct iovec, count);
974 if (vector == NULL) {
975 return NT_STATUS_NO_MEMORY;
977 mem_ctx = vector;
980 vector[0].iov_base = req->out.nbt_hdr;
981 vector[0].iov_len = 4;
982 SIVAL(req->out.nbt_hdr, 0, 0);
984 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
985 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
986 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
987 uint8_t *outhdr = NULL;
988 uint8_t *outbody = NULL;
989 uint32_t next_command_ofs = 0;
990 struct iovec *current = &vector[idx];
992 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
993 /* we have a next command -
994 * setup for the error case. */
995 next_command_ofs = SMB2_HDR_BODY + 9;
998 if (idx == 1) {
999 outhdr = req->out._hdr;
1000 } else {
1001 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1002 OUTVEC_ALLOC_SIZE);
1003 if (outhdr == NULL) {
1004 return NT_STATUS_NO_MEMORY;
1008 outbody = outhdr + SMB2_HDR_BODY;
1011 * SMBD_SMB2_TF_IOV_OFS might be used later
1013 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1014 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1016 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1017 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1019 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1020 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1022 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1023 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1025 /* setup the SMB2 header */
1026 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1027 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1028 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1029 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1030 SIVAL(outhdr, SMB2_HDR_STATUS,
1031 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1032 SSVAL(outhdr, SMB2_HDR_OPCODE,
1033 SVAL(inhdr, SMB2_HDR_OPCODE));
1034 SIVAL(outhdr, SMB2_HDR_FLAGS,
1035 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1036 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1037 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1038 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1039 SIVAL(outhdr, SMB2_HDR_PID,
1040 IVAL(inhdr, SMB2_HDR_PID));
1041 SIVAL(outhdr, SMB2_HDR_TID,
1042 IVAL(inhdr, SMB2_HDR_TID));
1043 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1044 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1045 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1046 inhdr + SMB2_HDR_SIGNATURE, 16);
1048 /* setup error body header */
1049 SSVAL(outbody, 0x00, 0x08 + 1);
1050 SSVAL(outbody, 0x02, 0);
1051 SIVAL(outbody, 0x04, 0);
1054 req->out.vector = vector;
1055 req->out.vector_count = count;
1057 /* setup the length of the NBT packet */
1058 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1059 if (!ok) {
1060 return NT_STATUS_INVALID_PARAMETER_MIX;
1063 DLIST_ADD_END(xconn->smb2.requests, req);
1065 return NT_STATUS_OK;
1068 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1069 const char *reason,
1070 const char *location)
1072 struct smbXsrv_client *client = xconn->client;
1074 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1075 smbXsrv_connection_dbg(xconn), reason, location));
1077 if (client->connections->next != NULL) {
1078 /* TODO: cancel pending requests */
1079 DLIST_REMOVE(client->connections, xconn);
1080 TALLOC_FREE(xconn);
1081 return;
1085 * The last connection was disconnected
1087 exit_server_cleanly(reason);
1090 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1091 struct iovec *outvec,
1092 const struct iovec *srcvec)
1094 const uint8_t *srctf;
1095 size_t srctf_len;
1096 const uint8_t *srchdr;
1097 size_t srchdr_len;
1098 const uint8_t *srcbody;
1099 size_t srcbody_len;
1100 const uint8_t *expected_srcbody;
1101 const uint8_t *srcdyn;
1102 size_t srcdyn_len;
1103 const uint8_t *expected_srcdyn;
1104 uint8_t *dsttf;
1105 uint8_t *dsthdr;
1106 uint8_t *dstbody;
1107 uint8_t *dstdyn;
1109 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1110 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1111 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1112 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1113 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1114 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1115 expected_srcbody = srchdr + SMB2_HDR_BODY;
1116 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1117 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1118 expected_srcdyn = srcbody + 8;
1120 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1121 return false;
1124 if (srchdr_len != SMB2_HDR_BODY) {
1125 return false;
1128 if (srctf_len == SMB2_TF_HDR_SIZE) {
1129 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1130 if (dsttf == NULL) {
1131 return false;
1133 } else {
1134 dsttf = NULL;
1136 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1137 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1139 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1140 * be allocated with size OUTVEC_ALLOC_SIZE. */
1142 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1143 if (dsthdr == NULL) {
1144 return false;
1146 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1147 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1150 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1151 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1152 * then duplicate this. Else use talloc_memdup().
1155 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1156 dstbody = dsthdr + SMB2_HDR_BODY;
1157 } else {
1158 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1159 if (dstbody == NULL) {
1160 return false;
1163 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1164 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1167 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1168 * pointing to
1169 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1170 * then duplicate this. Else use talloc_memdup().
1173 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1174 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1175 } else if (srcdyn == NULL) {
1176 dstdyn = NULL;
1177 } else {
1178 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1179 if (dstdyn == NULL) {
1180 return false;
1183 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1184 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1186 return true;
1189 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1191 struct smbd_smb2_request *newreq = NULL;
1192 struct iovec *outvec = NULL;
1193 int count = req->out.vector_count;
1194 int i;
1195 bool ok;
1197 newreq = smbd_smb2_request_allocate(req->xconn);
1198 if (!newreq) {
1199 return NULL;
1202 newreq->sconn = req->sconn;
1203 newreq->xconn = req->xconn;
1204 newreq->session = req->session;
1205 newreq->do_encryption = req->do_encryption;
1206 newreq->do_signing = req->do_signing;
1207 newreq->current_idx = req->current_idx;
1209 outvec = talloc_zero_array(newreq, struct iovec, count);
1210 if (!outvec) {
1211 TALLOC_FREE(newreq);
1212 return NULL;
1214 newreq->out.vector = outvec;
1215 newreq->out.vector_count = count;
1217 /* Setup the outvec's identically to req. */
1218 outvec[0].iov_base = newreq->out.nbt_hdr;
1219 outvec[0].iov_len = 4;
1220 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1222 /* Setup the vectors identically to the ones in req. */
1223 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1224 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1225 break;
1229 if (i < count) {
1230 /* Alloc failed. */
1231 TALLOC_FREE(newreq);
1232 return NULL;
1235 ok = smb2_setup_nbt_length(newreq->out.vector,
1236 newreq->out.vector_count);
1237 if (!ok) {
1238 TALLOC_FREE(newreq);
1239 return NULL;
1242 return newreq;
1245 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1247 struct smbXsrv_connection *xconn = req->xconn;
1248 int first_idx = 1;
1249 struct iovec *firsttf = NULL;
1250 struct iovec *outhdr_v = NULL;
1251 uint8_t *outhdr = NULL;
1252 struct smbd_smb2_request *nreq = NULL;
1253 NTSTATUS status;
1254 bool ok;
1256 /* Create a new smb2 request we'll use
1257 for the interim return. */
1258 nreq = dup_smb2_req(req);
1259 if (!nreq) {
1260 return NT_STATUS_NO_MEMORY;
1263 /* Lose the last X out vectors. They're the
1264 ones we'll be using for the async reply. */
1265 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1267 ok = smb2_setup_nbt_length(nreq->out.vector,
1268 nreq->out.vector_count);
1269 if (!ok) {
1270 return NT_STATUS_INVALID_PARAMETER_MIX;
1273 /* Step back to the previous reply. */
1274 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1275 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1276 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1277 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1278 /* And end the chain. */
1279 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1281 /* Calculate outgoing credits */
1282 smb2_calculate_credits(req, nreq);
1284 if (DEBUGLEVEL >= 10) {
1285 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1286 (unsigned int)nreq->current_idx );
1287 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1288 (unsigned int)nreq->out.vector_count );
1289 print_req_vectors(nreq);
1293 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1294 * we need to sign/encrypt here with the last/first key we remembered
1296 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1297 status = smb2_signing_encrypt_pdu(req->first_key,
1298 xconn->smb2.server.cipher,
1299 firsttf,
1300 nreq->out.vector_count - first_idx);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 return status;
1304 } else if (req->last_key.length > 0) {
1305 status = smb2_signing_sign_pdu(req->last_key,
1306 xconn->protocol,
1307 outhdr_v,
1308 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1309 if (!NT_STATUS_IS_OK(status)) {
1310 return status;
1314 nreq->queue_entry.mem_ctx = nreq;
1315 nreq->queue_entry.vector = nreq->out.vector;
1316 nreq->queue_entry.count = nreq->out.vector_count;
1317 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1318 xconn->smb2.send_queue_len++;
1320 status = smbd_smb2_flush_send_queue(xconn);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 return status;
1325 return NT_STATUS_OK;
1328 struct smbd_smb2_request_pending_state {
1329 struct smbd_smb2_send_queue queue_entry;
1330 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1331 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1334 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1335 struct tevent_timer *te,
1336 struct timeval current_time,
1337 void *private_data);
1339 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1340 struct tevent_req *subreq,
1341 uint32_t defer_time)
1343 NTSTATUS status;
1344 struct timeval defer_endtime;
1345 uint8_t *outhdr = NULL;
1346 uint32_t flags;
1348 if (!tevent_req_is_in_progress(subreq)) {
1350 * This is a performance optimization,
1351 * it avoids one tevent_loop iteration,
1352 * which means we avoid one
1353 * talloc_stackframe_pool/talloc_free pair.
1355 tevent_req_notify_callback(subreq);
1356 return NT_STATUS_OK;
1359 req->subreq = subreq;
1360 subreq = NULL;
1362 if (req->async_te) {
1363 /* We're already async. */
1364 return NT_STATUS_OK;
1367 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1368 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1369 if (flags & SMB2_HDR_FLAG_ASYNC) {
1370 /* We're already async. */
1371 return NT_STATUS_OK;
1374 if (req->async_internal) {
1376 * An SMB2 request implementation wants to handle the request
1377 * asynchronously "internally" while keeping synchronous
1378 * behaviour for the SMB2 request. This means we don't send an
1379 * interim response and we can allow processing of compound SMB2
1380 * requests (cf the subsequent check) for all cases.
1382 return NT_STATUS_OK;
1385 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1387 * We're trying to go async in a compound request
1388 * chain. This is only allowed for opens that cause an
1389 * oplock break or for the last operation in the
1390 * chain, otherwise it is not allowed. See
1391 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1393 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1395 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1397 * Cancel the outstanding request.
1399 bool ok = tevent_req_cancel(req->subreq);
1400 if (ok) {
1401 return NT_STATUS_OK;
1403 TALLOC_FREE(req->subreq);
1404 return smbd_smb2_request_error(req,
1405 NT_STATUS_INTERNAL_ERROR);
1409 if (DEBUGLEVEL >= 10) {
1410 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1411 (unsigned int)req->current_idx );
1412 print_req_vectors(req);
1415 if (req->current_idx > 1) {
1417 * We're going async in a compound
1418 * chain after the first request has
1419 * already been processed. Send an
1420 * interim response containing the
1421 * set of replies already generated.
1423 int idx = req->current_idx;
1425 status = smb2_send_async_interim_response(req);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 return status;
1429 if (req->first_key.length > 0) {
1430 data_blob_clear_free(&req->first_key);
1433 req->current_idx = 1;
1436 * Re-arrange the in.vectors to remove what
1437 * we just sent.
1439 memmove(&req->in.vector[1],
1440 &req->in.vector[idx],
1441 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1442 req->in.vector_count = 1 + (req->in.vector_count - idx);
1444 /* Re-arrange the out.vectors to match. */
1445 memmove(&req->out.vector[1],
1446 &req->out.vector[idx],
1447 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1448 req->out.vector_count = 1 + (req->out.vector_count - idx);
1450 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1452 * We only have one remaining request as
1453 * we've processed everything else.
1454 * This is no longer a compound request.
1456 req->compound_related = false;
1457 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1458 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1459 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1462 if (req->last_key.length > 0) {
1463 data_blob_clear_free(&req->last_key);
1466 defer_endtime = timeval_current_ofs_usec(defer_time);
1467 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1468 req, defer_endtime,
1469 smbd_smb2_request_pending_timer,
1470 req);
1471 if (req->async_te == NULL) {
1472 return NT_STATUS_NO_MEMORY;
1475 return NT_STATUS_OK;
1478 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1479 struct smbXsrv_connection *xconn)
1481 struct smbXsrv_channel_global0 *c = NULL;
1482 NTSTATUS status;
1483 DATA_BLOB key = data_blob_null;
1485 status = smbXsrv_session_find_channel(session, xconn, &c);
1486 if (NT_STATUS_IS_OK(status)) {
1487 key = c->signing_key;
1490 if (key.length == 0) {
1491 key = session->global->signing_key;
1494 return key;
1497 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1498 uint64_t *new_nonce_high,
1499 uint64_t *new_nonce_low)
1501 uint64_t nonce_high;
1502 uint64_t nonce_low;
1504 session->nonce_low += 1;
1505 if (session->nonce_low == 0) {
1506 session->nonce_low += 1;
1507 session->nonce_high += 1;
1511 * CCM and GCM algorithms must never have their
1512 * nonce wrap, or the security of the whole
1513 * communication and the keys is destroyed.
1514 * We must drop the connection once we have
1515 * transfered too much data.
1517 * NOTE: We assume nonces greater than 8 bytes.
1519 if (session->nonce_high >= session->nonce_high_max) {
1520 return NT_STATUS_ENCRYPTION_FAILED;
1523 nonce_high = session->nonce_high_random;
1524 nonce_high += session->nonce_high;
1525 nonce_low = session->nonce_low;
1527 *new_nonce_high = nonce_high;
1528 *new_nonce_low = nonce_low;
1529 return NT_STATUS_OK;
1532 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1533 struct tevent_timer *te,
1534 struct timeval current_time,
1535 void *private_data)
1537 struct smbd_smb2_request *req =
1538 talloc_get_type_abort(private_data,
1539 struct smbd_smb2_request);
1540 struct smbXsrv_connection *xconn = req->xconn;
1541 struct smbd_smb2_request_pending_state *state = NULL;
1542 uint8_t *outhdr = NULL;
1543 const uint8_t *inhdr = NULL;
1544 uint8_t *tf = NULL;
1545 size_t tf_len = 0;
1546 uint8_t *hdr = NULL;
1547 uint8_t *body = NULL;
1548 uint8_t *dyn = NULL;
1549 uint32_t flags = 0;
1550 uint64_t session_id = 0;
1551 uint64_t message_id = 0;
1552 uint64_t nonce_high = 0;
1553 uint64_t nonce_low = 0;
1554 uint64_t async_id = 0;
1555 NTSTATUS status;
1556 bool ok;
1558 TALLOC_FREE(req->async_te);
1560 /* Ensure our final reply matches the interim one. */
1561 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1562 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1563 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1564 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1565 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1567 async_id = message_id; /* keep it simple for now... */
1569 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1570 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1572 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1573 "going async\n",
1574 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1575 (unsigned long long)async_id ));
1578 * What we send is identical to a smbd_smb2_request_error
1579 * packet with an error status of STATUS_PENDING. Make use
1580 * of this fact sometime when refactoring. JRA.
1583 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1584 if (state == NULL) {
1585 smbd_server_connection_terminate(xconn,
1586 nt_errstr(NT_STATUS_NO_MEMORY));
1587 return;
1590 tf = state->buf + NBT_HDR_SIZE;
1591 tf_len = SMB2_TF_HDR_SIZE;
1593 hdr = tf + SMB2_TF_HDR_SIZE;
1594 body = hdr + SMB2_HDR_BODY;
1595 dyn = body + 8;
1597 if (req->do_encryption) {
1598 status = smb2_get_new_nonce(req->session,
1599 &nonce_high,
1600 &nonce_low);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 smbd_server_connection_terminate(xconn,
1603 nt_errstr(status));
1604 return;
1608 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1609 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1610 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1611 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1613 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1614 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1615 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1616 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1617 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1619 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1620 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1621 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1622 SBVAL(hdr, SMB2_HDR_PID, async_id);
1623 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1624 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1625 memcpy(hdr+SMB2_HDR_SIGNATURE,
1626 outhdr+SMB2_HDR_SIGNATURE, 16);
1628 SSVAL(body, 0x00, 0x08 + 1);
1630 SCVAL(body, 0x02, 0);
1631 SCVAL(body, 0x03, 0);
1632 SIVAL(body, 0x04, 0);
1633 /* Match W2K8R2... */
1634 SCVAL(dyn, 0x00, 0x21);
1636 state->vector[0].iov_base = (void *)state->buf;
1637 state->vector[0].iov_len = NBT_HDR_SIZE;
1639 if (req->do_encryption) {
1640 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1641 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1642 } else {
1643 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1644 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1647 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1648 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1650 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1651 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1653 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1654 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1656 ok = smb2_setup_nbt_length(state->vector,
1657 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1658 if (!ok) {
1659 smbd_server_connection_terminate(
1660 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1661 return;
1664 /* Ensure we correctly go through crediting. Grant
1665 the credits now, and zero credits on the final
1666 response. */
1667 smb2_set_operation_credit(req->xconn,
1668 SMBD_SMB2_IN_HDR_IOV(req),
1669 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1671 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1673 if (DEBUGLVL(10)) {
1674 int i;
1676 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1677 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1678 (unsigned int)i,
1679 (unsigned int)ARRAY_SIZE(state->vector),
1680 (unsigned int)state->vector[i].iov_len);
1684 if (req->do_encryption) {
1685 struct smbXsrv_session *x = req->session;
1686 DATA_BLOB encryption_key = x->global->encryption_key;
1688 status = smb2_signing_encrypt_pdu(encryption_key,
1689 xconn->smb2.server.cipher,
1690 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1691 SMBD_SMB2_NUM_IOV_PER_REQ);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 smbd_server_connection_terminate(xconn,
1694 nt_errstr(status));
1695 return;
1697 } else if (req->do_signing) {
1698 struct smbXsrv_session *x = req->session;
1699 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1701 status = smb2_signing_sign_pdu(signing_key,
1702 xconn->protocol,
1703 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1704 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 smbd_server_connection_terminate(xconn,
1707 nt_errstr(status));
1708 return;
1712 state->queue_entry.mem_ctx = state;
1713 state->queue_entry.vector = state->vector;
1714 state->queue_entry.count = ARRAY_SIZE(state->vector);
1715 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1716 xconn->smb2.send_queue_len++;
1718 status = smbd_smb2_flush_send_queue(xconn);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 smbd_server_connection_terminate(xconn,
1721 nt_errstr(status));
1722 return;
1726 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1728 struct smbXsrv_connection *xconn = req->xconn;
1729 struct smbd_smb2_request *cur;
1730 const uint8_t *inhdr;
1731 uint32_t flags;
1732 uint64_t search_message_id;
1733 uint64_t search_async_id;
1734 uint64_t found_id;
1736 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1738 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1739 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1740 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1743 * We don't need the request anymore cancel requests never
1744 * have a response.
1746 * We defer the TALLOC_FREE(req) to the caller.
1748 DLIST_REMOVE(xconn->smb2.requests, req);
1750 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1751 const uint8_t *outhdr;
1752 uint64_t message_id;
1753 uint64_t async_id;
1755 if (cur->compound_related) {
1757 * Never cancel anything in a compound request.
1758 * Way too hard to deal with the result.
1760 continue;
1763 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1765 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1766 async_id = BVAL(outhdr, SMB2_HDR_PID);
1768 if (flags & SMB2_HDR_FLAG_ASYNC) {
1769 if (search_async_id == async_id) {
1770 found_id = async_id;
1771 break;
1773 } else {
1774 if (search_message_id == message_id) {
1775 found_id = message_id;
1776 break;
1781 if (cur && cur->subreq) {
1782 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1783 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1784 "cancel opcode[%s] mid %llu\n",
1785 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1786 (unsigned long long)found_id ));
1787 tevent_req_cancel(cur->subreq);
1790 return NT_STATUS_OK;
1793 /*************************************************************
1794 Ensure an incoming tid is a valid one for us to access.
1795 Change to the associated uid credentials and chdir to the
1796 valid tid directory.
1797 *************************************************************/
1799 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1801 const uint8_t *inhdr;
1802 uint32_t in_flags;
1803 uint32_t in_tid;
1804 struct smbXsrv_tcon *tcon;
1805 NTSTATUS status;
1806 NTTIME now = timeval_to_nttime(&req->request_time);
1808 req->tcon = NULL;
1810 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1812 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1813 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1815 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1816 in_tid = req->last_tid;
1819 req->last_tid = 0;
1821 status = smb2srv_tcon_lookup(req->session,
1822 in_tid, now, &tcon);
1823 if (!NT_STATUS_IS_OK(status)) {
1824 return status;
1827 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1828 return NT_STATUS_ACCESS_DENIED;
1831 if (!set_current_service(tcon->compat, 0, true)) {
1832 return NT_STATUS_ACCESS_DENIED;
1835 req->tcon = tcon;
1836 req->last_tid = in_tid;
1838 return NT_STATUS_OK;
1841 /*************************************************************
1842 Ensure an incoming session_id is a valid one for us to access.
1843 *************************************************************/
1845 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1847 const uint8_t *inhdr;
1848 uint32_t in_flags;
1849 uint16_t in_opcode;
1850 uint64_t in_session_id;
1851 struct smbXsrv_session *session = NULL;
1852 struct auth_session_info *session_info;
1853 NTSTATUS status;
1854 NTTIME now = timeval_to_nttime(&req->request_time);
1856 req->session = NULL;
1857 req->tcon = NULL;
1859 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1861 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1862 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1863 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1865 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1866 in_session_id = req->last_session_id;
1869 req->last_session_id = 0;
1871 /* look an existing session up */
1872 switch (in_opcode) {
1873 case SMB2_OP_SESSSETUP:
1875 * For a session bind request, we don't have the
1876 * channel set up at this point yet, so we defer
1877 * the verification that the connection belongs
1878 * to the session to the session setup code, which
1879 * can look at the session binding flags.
1881 status = smb2srv_session_lookup_client(req->xconn->client,
1882 in_session_id, now,
1883 &session);
1884 break;
1885 default:
1886 status = smb2srv_session_lookup_conn(req->xconn,
1887 in_session_id, now,
1888 &session);
1889 break;
1891 if (session) {
1892 req->session = session;
1893 req->last_session_id = in_session_id;
1895 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1896 switch (in_opcode) {
1897 case SMB2_OP_SESSSETUP:
1898 status = NT_STATUS_OK;
1899 break;
1900 default:
1901 break;
1904 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1905 switch (in_opcode) {
1906 case SMB2_OP_TCON:
1907 case SMB2_OP_CREATE:
1908 case SMB2_OP_GETINFO:
1909 case SMB2_OP_SETINFO:
1910 return NT_STATUS_INVALID_HANDLE;
1911 default:
1913 * Notice the check for
1914 * (session_info == NULL)
1915 * below.
1917 status = NT_STATUS_OK;
1918 break;
1921 if (!NT_STATUS_IS_OK(status)) {
1922 return status;
1925 session_info = session->global->auth_session_info;
1926 if (session_info == NULL) {
1927 return NT_STATUS_INVALID_HANDLE;
1930 if (in_session_id != req->xconn->client->last_session_id) {
1931 req->xconn->client->last_session_id = in_session_id;
1932 set_current_user_info(session_info->unix_info->sanitized_username,
1933 session_info->unix_info->unix_name,
1934 session_info->info->domain_name);
1937 return NT_STATUS_OK;
1940 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1941 uint32_t data_length)
1943 struct smbXsrv_connection *xconn = req->xconn;
1944 uint16_t needed_charge;
1945 uint16_t credit_charge = 1;
1946 const uint8_t *inhdr;
1948 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1950 if (xconn->smb2.credits.multicredit) {
1951 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1952 credit_charge = MAX(credit_charge, 1);
1955 needed_charge = (data_length - 1)/ 65536 + 1;
1957 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1958 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1959 credit_charge, needed_charge));
1961 if (needed_charge > credit_charge) {
1962 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1963 credit_charge, needed_charge));
1964 return NT_STATUS_INVALID_PARAMETER;
1967 return NT_STATUS_OK;
1970 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1971 size_t expected_body_size)
1973 struct iovec *inhdr_v;
1974 const uint8_t *inhdr;
1975 uint16_t opcode;
1976 const uint8_t *inbody;
1977 size_t body_size;
1978 size_t min_dyn_size = expected_body_size & 0x00000001;
1979 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1982 * The following should be checked already.
1984 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1985 return NT_STATUS_INTERNAL_ERROR;
1987 if (req->current_idx > max_idx) {
1988 return NT_STATUS_INTERNAL_ERROR;
1991 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1992 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1993 return NT_STATUS_INTERNAL_ERROR;
1995 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1996 return NT_STATUS_INTERNAL_ERROR;
1999 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2000 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2002 switch (opcode) {
2003 case SMB2_OP_IOCTL:
2004 case SMB2_OP_GETINFO:
2005 min_dyn_size = 0;
2006 break;
2007 case SMB2_OP_WRITE:
2008 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2009 if (req->smb1req->unread_bytes < min_dyn_size) {
2010 return NT_STATUS_INVALID_PARAMETER;
2013 min_dyn_size = 0;
2015 break;
2019 * Now check the expected body size,
2020 * where the last byte might be in the
2021 * dynamic section..
2023 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2024 return NT_STATUS_INVALID_PARAMETER;
2026 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2027 return NT_STATUS_INVALID_PARAMETER;
2030 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2032 body_size = SVAL(inbody, 0x00);
2033 if (body_size != expected_body_size) {
2034 return NT_STATUS_INVALID_PARAMETER;
2037 return NT_STATUS_OK;
2040 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2042 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2044 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2045 SMBXSRV_ENCRYPTION_DESIRED |
2046 SMBXSRV_ENCRYPTION_REQUIRED)));
2049 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2051 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2052 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2055 /* Set a flag if not already set, return true if set */
2056 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2058 if ((flag == 0) || (*flags & flag)) {
2059 return false;
2062 *flags |= flag;
2063 return true;
2067 * Update encryption state tracking flags, this can be used to
2068 * determine whether whether the session or tcon is "encrypted".
2070 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2071 uint16_t opcode,
2072 bool *update_session_globalp,
2073 bool *update_tcon_globalp)
2075 /* Default: assume unecrypted and unsigned */
2076 struct smbXsrv_session *session = req->session;
2077 struct smbXsrv_tcon *tcon = req->tcon;
2078 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2079 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2080 bool update_session = false;
2081 bool update_tcon = false;
2083 if (req->was_encrypted && req->do_encryption) {
2084 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2085 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2086 } else {
2087 /* Unencrypted packet, can be signed */
2088 if (req->do_signing) {
2089 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2090 } else if (opcode == SMB2_OP_CANCEL) {
2091 /* Cancel requests are allowed to skip signing */
2092 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2096 update_session |= smbXsrv_set_crypto_flag(
2097 &session->global->encryption_flags, encrypt_flag);
2098 update_session |= smbXsrv_set_crypto_flag(
2099 &session->global->signing_flags, sign_flag);
2101 if (tcon) {
2102 update_tcon |= smbXsrv_set_crypto_flag(
2103 &tcon->global->encryption_flags, encrypt_flag);
2104 update_tcon |= smbXsrv_set_crypto_flag(
2105 &tcon->global->signing_flags, sign_flag);
2108 *update_session_globalp = update_session;
2109 *update_tcon_globalp = update_tcon;
2110 return;
2113 bool smbXsrv_is_signed(uint8_t signing_flags)
2116 * Signing is always enabled, so unless we got an unsigned
2117 * packet and at least one signed packet that was not
2118 * encrypted, the session or tcon is "signed".
2120 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2121 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2124 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2126 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2127 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2130 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2131 struct smbd_smb2_request *req,
2132 bool modify_call)
2134 struct smbXsrv_connection *xconn = req->xconn;
2135 const uint8_t *inhdr;
2136 uint16_t channel_sequence;
2137 uint32_t flags;
2138 int cmp;
2139 struct smbXsrv_open *op;
2140 bool update_open = false;
2141 NTSTATUS status = NT_STATUS_OK;
2143 req->request_counters_updated = false;
2145 if (xconn->protocol < PROTOCOL_SMB2_22) {
2146 return NT_STATUS_OK;
2149 if (req->compat_chain_fsp == NULL) {
2150 return NT_STATUS_OK;
2153 op = req->compat_chain_fsp->op;
2154 if (op == NULL) {
2155 return NT_STATUS_OK;
2158 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2159 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2160 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2162 cmp = channel_sequence - op->global->channel_sequence;
2164 if (abs(cmp) > INT16_MAX) {
2166 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2168 * If the channel sequence number of the request and the one
2169 * known to the server are not equal, the channel sequence
2170 * number and outstanding request counts are only updated
2171 * "... if the unsigned difference using 16-bit arithmetic
2172 * between ChannelSequence and Open.ChannelSequence is less than
2173 * or equal to 0x7FFF ...".
2174 * Otherwise, an error is returned for the modifying
2175 * calls write, set_info, and ioctl.
2177 * There are currently two issues with the description:
2179 * * For the other calls, the document seems to imply
2180 * that processing continues without adapting the
2181 * counters (if the sequence numbers are not equal).
2183 * TODO: This needs clarification!
2185 * * Also, the behaviour if the difference is larger
2186 * than 0x7FFF is not clear. The document seems to
2187 * imply that if such a difference is reached,
2188 * the server starts to ignore the counters or
2189 * in the case of the modifying calls, return errors.
2191 * TODO: This needs clarification!
2193 * At this point Samba tries to be a little more
2194 * clever than the description in the MS-SMB2 document
2195 * by heuristically detecting and properly treating
2196 * a 16 bit overflow of the client-submitted sequence
2197 * number:
2199 * If the stored channel squence number is more than
2200 * 0x7FFF larger than the one from the request, then
2201 * the client-provided sequence number has likely
2202 * overflown. We treat this case as valid instead
2203 * of as failure.
2205 * The MS-SMB2 behaviour would be setting cmp = -1.
2207 cmp *= -1;
2210 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2211 if (cmp == 0) {
2212 op->request_count += 1;
2213 req->request_counters_updated = true;
2214 } else if (cmp > 0) {
2215 op->pre_request_count += op->request_count;
2216 op->request_count = 1;
2217 op->global->channel_sequence = channel_sequence;
2218 update_open = true;
2219 req->request_counters_updated = true;
2220 } else if (modify_call) {
2221 return NT_STATUS_FILE_NOT_AVAILABLE;
2223 } else {
2224 if (cmp == 0 && op->pre_request_count == 0) {
2225 op->request_count += 1;
2226 req->request_counters_updated = true;
2227 } else if (cmp > 0 && op->pre_request_count == 0) {
2228 op->pre_request_count += op->request_count;
2229 op->request_count = 1;
2230 op->global->channel_sequence = channel_sequence;
2231 update_open = true;
2232 req->request_counters_updated = true;
2233 } else if (modify_call) {
2234 return NT_STATUS_FILE_NOT_AVAILABLE;
2238 if (update_open) {
2239 status = smbXsrv_open_update(op);
2242 return status;
2245 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2247 struct smbXsrv_connection *xconn = req->xconn;
2248 const struct smbd_smb2_dispatch_table *call = NULL;
2249 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2250 const uint8_t *inhdr;
2251 uint16_t opcode;
2252 uint32_t flags;
2253 uint64_t mid;
2254 NTSTATUS status;
2255 NTSTATUS session_status;
2256 uint32_t allowed_flags;
2257 NTSTATUS return_value;
2258 struct smbXsrv_session *x = NULL;
2259 bool signing_required = false;
2260 bool encryption_desired = false;
2261 bool encryption_required = false;
2263 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2265 DO_PROFILE_INC(request);
2267 /* TODO: verify more things */
2269 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2270 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2271 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2272 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2273 smb2_opcode_name(opcode),
2274 (unsigned long long)mid));
2276 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2278 * once the protocol is negotiated
2279 * SMB2_OP_NEGPROT is not allowed anymore
2281 if (opcode == SMB2_OP_NEGPROT) {
2282 /* drop the connection */
2283 return NT_STATUS_INVALID_PARAMETER;
2285 } else {
2287 * if the protocol is not negotiated yet
2288 * only SMB2_OP_NEGPROT is allowed.
2290 if (opcode != SMB2_OP_NEGPROT) {
2291 /* drop the connection */
2292 return NT_STATUS_INVALID_PARAMETER;
2297 * Check if the client provided a valid session id,
2298 * if so smbd_smb2_request_check_session() calls
2299 * set_current_user_info().
2301 * As some command don't require a valid session id
2302 * we defer the check of the session_status
2304 session_status = smbd_smb2_request_check_session(req);
2305 x = req->session;
2306 if (x != NULL) {
2307 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2308 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2309 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2312 req->async_internal = false;
2313 req->do_signing = false;
2314 req->do_encryption = false;
2315 req->was_encrypted = false;
2316 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2317 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2318 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2320 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2321 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2322 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2323 (unsigned long long)x->global->session_wire_id,
2324 (unsigned long long)tf_session_id));
2326 * TODO: windows allows this...
2327 * should we drop the connection?
2329 * For now we just return ACCESS_DENIED
2330 * (Windows clients never trigger this)
2331 * and wait for an update of [MS-SMB2].
2333 return smbd_smb2_request_error(req,
2334 NT_STATUS_ACCESS_DENIED);
2337 req->was_encrypted = true;
2340 if (encryption_required && !req->was_encrypted) {
2341 return smbd_smb2_request_error(req,
2342 NT_STATUS_ACCESS_DENIED);
2345 call = smbd_smb2_call(opcode);
2346 if (call == NULL) {
2347 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2350 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2351 SMB2_HDR_FLAG_SIGNED |
2352 SMB2_HDR_FLAG_DFS;
2353 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2354 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2356 if (opcode == SMB2_OP_NEGPROT) {
2357 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2358 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2361 if (opcode == SMB2_OP_CANCEL) {
2362 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2364 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2365 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2367 if ((flags & ~allowed_flags) != 0) {
2368 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2371 if (flags & SMB2_HDR_FLAG_CHAINED) {
2373 * This check is mostly for giving the correct error code
2374 * for compounded requests.
2376 if (!NT_STATUS_IS_OK(session_status)) {
2377 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2379 } else {
2380 req->compat_chain_fsp = NULL;
2383 if (req->was_encrypted) {
2384 signing_required = false;
2385 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2386 DATA_BLOB signing_key = data_blob_null;
2388 if (x == NULL) {
2390 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2391 * If the SMB2 header of the SMB2 NEGOTIATE
2392 * request has the SMB2_FLAGS_SIGNED bit set in the
2393 * Flags field, the server MUST fail the request
2394 * with STATUS_INVALID_PARAMETER.
2396 * Microsoft test tool checks this.
2399 if ((opcode == SMB2_OP_NEGPROT) &&
2400 (flags & SMB2_HDR_FLAG_SIGNED)) {
2401 status = NT_STATUS_INVALID_PARAMETER;
2402 } else {
2403 status = NT_STATUS_USER_SESSION_DELETED;
2405 return smbd_smb2_request_error(req, status);
2408 signing_key = smbd_smb2_signing_key(x, xconn);
2411 * If we have a signing key, we should
2412 * sign the response
2414 if (signing_key.length > 0) {
2415 req->do_signing = true;
2418 status = smb2_signing_check_pdu(signing_key,
2419 xconn->protocol,
2420 SMBD_SMB2_IN_HDR_IOV(req),
2421 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2422 if (!NT_STATUS_IS_OK(status)) {
2423 return smbd_smb2_request_error(req, status);
2427 * Now that we know the request was correctly signed
2428 * we have to sign the response too.
2430 req->do_signing = true;
2432 if (!NT_STATUS_IS_OK(session_status)) {
2433 return smbd_smb2_request_error(req, session_status);
2435 } else if (opcode == SMB2_OP_CANCEL) {
2436 /* Cancel requests are allowed to skip the signing */
2437 } else if (signing_required) {
2439 * If signing is required we try to sign
2440 * a possible error response
2442 req->do_signing = true;
2443 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2446 if (flags & SMB2_HDR_FLAG_CHAINED) {
2447 req->compound_related = true;
2450 if (call->need_session) {
2451 if (!NT_STATUS_IS_OK(session_status)) {
2452 return smbd_smb2_request_error(req, session_status);
2456 if (call->need_tcon) {
2457 SMB_ASSERT(call->need_session);
2460 * This call needs to be run as user.
2462 * smbd_smb2_request_check_tcon()
2463 * calls change_to_user() on success.
2465 status = smbd_smb2_request_check_tcon(req);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 return smbd_smb2_request_error(req, status);
2469 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2470 encryption_desired = true;
2472 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2473 encryption_required = true;
2475 if (encryption_required && !req->was_encrypted) {
2476 return smbd_smb2_request_error(req,
2477 NT_STATUS_ACCESS_DENIED);
2481 if (req->was_encrypted || encryption_desired) {
2482 req->do_encryption = true;
2485 if (req->session) {
2486 bool update_session_global = false;
2487 bool update_tcon_global = false;
2489 smb2srv_update_crypto_flags(req, opcode,
2490 &update_session_global,
2491 &update_tcon_global);
2493 if (update_session_global) {
2494 status = smbXsrv_session_update(x);
2495 if (!NT_STATUS_IS_OK(status)) {
2496 return smbd_smb2_request_error(req, status);
2499 if (update_tcon_global) {
2500 status = smbXsrv_tcon_update(req->tcon);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 return smbd_smb2_request_error(req, status);
2507 if (call->fileid_ofs != 0) {
2508 size_t needed = call->fileid_ofs + 16;
2509 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2510 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2511 uint64_t file_id_persistent;
2512 uint64_t file_id_volatile;
2513 struct files_struct *fsp;
2515 SMB_ASSERT(call->need_tcon);
2517 if (needed > body_size) {
2518 return smbd_smb2_request_error(req,
2519 NT_STATUS_INVALID_PARAMETER);
2522 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2523 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2525 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2526 if (fsp == NULL) {
2527 if (!call->allow_invalid_fileid) {
2528 return smbd_smb2_request_error(req,
2529 NT_STATUS_FILE_CLOSED);
2532 if (file_id_persistent != UINT64_MAX) {
2533 return smbd_smb2_request_error(req,
2534 NT_STATUS_FILE_CLOSED);
2536 if (file_id_volatile != UINT64_MAX) {
2537 return smbd_smb2_request_error(req,
2538 NT_STATUS_FILE_CLOSED);
2543 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 return smbd_smb2_request_error(req, status);
2548 if (call->as_root) {
2549 SMB_ASSERT(call->fileid_ofs == 0);
2550 /* This call needs to be run as root */
2551 change_to_root_user();
2552 } else {
2553 SMB_ASSERT(call->need_tcon);
2556 #define _INBYTES(_r) \
2557 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2559 switch (opcode) {
2560 case SMB2_OP_NEGPROT:
2561 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2562 req->profile, _INBYTES(req));
2563 return_value = smbd_smb2_request_process_negprot(req);
2564 break;
2566 case SMB2_OP_SESSSETUP:
2567 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2568 req->profile, _INBYTES(req));
2569 return_value = smbd_smb2_request_process_sesssetup(req);
2570 break;
2572 case SMB2_OP_LOGOFF:
2573 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2574 req->profile, _INBYTES(req));
2575 return_value = smbd_smb2_request_process_logoff(req);
2576 break;
2578 case SMB2_OP_TCON:
2579 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2580 req->profile, _INBYTES(req));
2581 return_value = smbd_smb2_request_process_tcon(req);
2582 break;
2584 case SMB2_OP_TDIS:
2585 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2586 req->profile, _INBYTES(req));
2587 return_value = smbd_smb2_request_process_tdis(req);
2588 break;
2590 case SMB2_OP_CREATE:
2591 if (req->subreq == NULL) {
2592 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2593 req->profile, _INBYTES(req));
2594 } else {
2595 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2597 return_value = smbd_smb2_request_process_create(req);
2598 break;
2600 case SMB2_OP_CLOSE:
2601 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2602 req->profile, _INBYTES(req));
2603 return_value = smbd_smb2_request_process_close(req);
2604 break;
2606 case SMB2_OP_FLUSH:
2607 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2608 req->profile, _INBYTES(req));
2609 return_value = smbd_smb2_request_process_flush(req);
2610 break;
2612 case SMB2_OP_READ:
2613 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2614 req->profile, _INBYTES(req));
2615 return_value = smbd_smb2_request_process_read(req);
2616 break;
2618 case SMB2_OP_WRITE:
2619 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2620 req->profile, _INBYTES(req));
2621 return_value = smbd_smb2_request_process_write(req);
2622 break;
2624 case SMB2_OP_LOCK:
2625 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2626 req->profile, _INBYTES(req));
2627 return_value = smbd_smb2_request_process_lock(req);
2628 break;
2630 case SMB2_OP_IOCTL:
2631 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2632 req->profile, _INBYTES(req));
2633 return_value = smbd_smb2_request_process_ioctl(req);
2634 break;
2636 case SMB2_OP_CANCEL:
2637 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2638 req->profile, _INBYTES(req));
2639 return_value = smbd_smb2_request_process_cancel(req);
2640 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2643 * We don't need the request anymore cancel requests never
2644 * have a response.
2646 * smbd_smb2_request_process_cancel() already called
2647 * DLIST_REMOVE(xconn->smb2.requests, req);
2649 TALLOC_FREE(req);
2651 break;
2653 case SMB2_OP_KEEPALIVE:
2654 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2655 req->profile, _INBYTES(req));
2656 return_value = smbd_smb2_request_process_keepalive(req);
2657 break;
2659 case SMB2_OP_QUERY_DIRECTORY:
2660 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2661 req->profile, _INBYTES(req));
2662 return_value = smbd_smb2_request_process_query_directory(req);
2663 break;
2665 case SMB2_OP_NOTIFY:
2666 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2667 req->profile, _INBYTES(req));
2668 return_value = smbd_smb2_request_process_notify(req);
2669 break;
2671 case SMB2_OP_GETINFO:
2672 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2673 req->profile, _INBYTES(req));
2674 return_value = smbd_smb2_request_process_getinfo(req);
2675 break;
2677 case SMB2_OP_SETINFO:
2678 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2679 req->profile, _INBYTES(req));
2680 return_value = smbd_smb2_request_process_setinfo(req);
2681 break;
2683 case SMB2_OP_BREAK:
2684 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2685 req->profile, _INBYTES(req));
2686 return_value = smbd_smb2_request_process_break(req);
2687 break;
2689 default:
2690 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2691 break;
2693 return return_value;
2696 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2698 struct smbXsrv_connection *xconn = req->xconn;
2699 const uint8_t *inhdr;
2700 uint16_t channel_sequence;
2701 struct smbXsrv_open *op;
2703 if (!req->request_counters_updated) {
2704 return;
2707 if (xconn->protocol < PROTOCOL_SMB2_22) {
2708 return;
2711 if (req->compat_chain_fsp == NULL) {
2712 return;
2715 op = req->compat_chain_fsp->op;
2716 if (op == NULL) {
2717 return;
2720 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2721 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2723 if (op->global->channel_sequence == channel_sequence) {
2724 SMB_ASSERT(op->request_count > 0);
2725 op->request_count -= 1;
2726 } else {
2727 SMB_ASSERT(op->pre_request_count > 0);
2728 op->pre_request_count -= 1;
2732 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2734 struct smbXsrv_connection *xconn = req->xconn;
2735 int first_idx = 1;
2736 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2737 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2738 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2739 NTSTATUS status;
2740 bool ok;
2742 req->subreq = NULL;
2743 TALLOC_FREE(req->async_te);
2745 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2746 smbd_smb2_request_reply_update_counts(req);
2748 if (req->do_encryption &&
2749 (firsttf->iov_len == 0) &&
2750 (req->first_key.length == 0) &&
2751 (req->session != NULL) &&
2752 (req->session->global->encryption_key.length != 0))
2754 DATA_BLOB encryption_key = req->session->global->encryption_key;
2755 uint8_t *tf;
2756 uint64_t session_id = req->session->global->session_wire_id;
2757 uint64_t nonce_high;
2758 uint64_t nonce_low;
2760 status = smb2_get_new_nonce(req->session,
2761 &nonce_high,
2762 &nonce_low);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 return status;
2768 * We need to place the SMB2_TRANSFORM header before the
2769 * first SMB2 header
2773 * we need to remember the encryption key
2774 * and defer the signing/encryption until
2775 * we are sure that we do not change
2776 * the header again.
2778 req->first_key = data_blob_dup_talloc(req, encryption_key);
2779 if (req->first_key.data == NULL) {
2780 return NT_STATUS_NO_MEMORY;
2783 tf = talloc_zero_array(req, uint8_t,
2784 SMB2_TF_HDR_SIZE);
2785 if (tf == NULL) {
2786 return NT_STATUS_NO_MEMORY;
2789 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2790 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2791 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2792 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2794 firsttf->iov_base = (void *)tf;
2795 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2798 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2799 (req->last_key.length > 0) &&
2800 (firsttf->iov_len == 0))
2802 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2803 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2806 * As we are sure the header of the last request in the
2807 * compound chain will not change, we can to sign here
2808 * with the last signing key we remembered.
2810 status = smb2_signing_sign_pdu(req->last_key,
2811 xconn->protocol,
2812 lasthdr,
2813 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2814 if (!NT_STATUS_IS_OK(status)) {
2815 return status;
2818 if (req->last_key.length > 0) {
2819 data_blob_clear_free(&req->last_key);
2822 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2823 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2825 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2827 if (req->current_idx < req->out.vector_count) {
2829 * We must process the remaining compound
2830 * SMB2 requests before any new incoming SMB2
2831 * requests. This is because incoming SMB2
2832 * requests may include a cancel for a
2833 * compound request we haven't processed
2834 * yet.
2836 struct tevent_immediate *im = tevent_create_immediate(req);
2837 if (!im) {
2838 return NT_STATUS_NO_MEMORY;
2841 if (req->do_signing && firsttf->iov_len == 0) {
2842 struct smbXsrv_session *x = req->session;
2843 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2846 * we need to remember the signing key
2847 * and defer the signing until
2848 * we are sure that we do not change
2849 * the header again.
2851 req->last_key = data_blob_dup_talloc(req, signing_key);
2852 if (req->last_key.data == NULL) {
2853 return NT_STATUS_NO_MEMORY;
2857 tevent_schedule_immediate(im,
2858 req->sconn->ev_ctx,
2859 smbd_smb2_request_dispatch_immediate,
2860 req);
2861 return NT_STATUS_OK;
2864 if (req->compound_related) {
2865 req->compound_related = false;
2868 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2869 if (!ok) {
2870 return NT_STATUS_INVALID_PARAMETER_MIX;
2873 /* Set credit for these operations (zero credits if this
2874 is a final reply for an async operation). */
2875 smb2_calculate_credits(req, req);
2878 * now check if we need to sign the current response
2880 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2881 status = smb2_signing_encrypt_pdu(req->first_key,
2882 xconn->smb2.server.cipher,
2883 firsttf,
2884 req->out.vector_count - first_idx);
2885 if (!NT_STATUS_IS_OK(status)) {
2886 return status;
2888 } else if (req->do_signing) {
2889 struct smbXsrv_session *x = req->session;
2890 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2892 status = smb2_signing_sign_pdu(signing_key,
2893 xconn->protocol,
2894 outhdr,
2895 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2896 if (!NT_STATUS_IS_OK(status)) {
2897 return status;
2900 if (req->first_key.length > 0) {
2901 data_blob_clear_free(&req->first_key);
2904 if (req->preauth != NULL) {
2905 struct hc_sha512state sctx;
2906 int i;
2908 samba_SHA512_Init(&sctx);
2909 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2910 sizeof(req->preauth->sha512_value));
2911 for (i = 1; i < req->in.vector_count; i++) {
2912 samba_SHA512_Update(&sctx,
2913 req->in.vector[i].iov_base,
2914 req->in.vector[i].iov_len);
2916 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2918 samba_SHA512_Init(&sctx);
2919 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2920 sizeof(req->preauth->sha512_value));
2921 for (i = 1; i < req->out.vector_count; i++) {
2922 samba_SHA512_Update(&sctx,
2923 req->out.vector[i].iov_base,
2924 req->out.vector[i].iov_len);
2926 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2928 req->preauth = NULL;
2931 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2932 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2933 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2934 /* Dynamic part is NULL. Chop it off,
2935 We're going to send it via sendfile. */
2936 req->out.vector_count -= 1;
2940 * We're done with this request -
2941 * move it off the "being processed" queue.
2943 DLIST_REMOVE(xconn->smb2.requests, req);
2945 req->queue_entry.mem_ctx = req;
2946 req->queue_entry.vector = req->out.vector;
2947 req->queue_entry.count = req->out.vector_count;
2948 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2949 xconn->smb2.send_queue_len++;
2951 status = smbd_smb2_flush_send_queue(xconn);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 return status;
2956 return NT_STATUS_OK;
2959 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2961 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2962 struct tevent_immediate *im,
2963 void *private_data)
2965 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2966 struct smbd_smb2_request);
2967 struct smbXsrv_connection *xconn = req->xconn;
2968 NTSTATUS status;
2970 TALLOC_FREE(im);
2972 if (DEBUGLEVEL >= 10) {
2973 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2974 req->current_idx, req->in.vector_count));
2975 print_req_vectors(req);
2978 status = smbd_smb2_request_dispatch(req);
2979 if (!NT_STATUS_IS_OK(status)) {
2980 smbd_server_connection_terminate(xconn, nt_errstr(status));
2981 return;
2984 status = smbd_smb2_request_next_incoming(xconn);
2985 if (!NT_STATUS_IS_OK(status)) {
2986 smbd_server_connection_terminate(xconn, nt_errstr(status));
2987 return;
2991 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2992 NTSTATUS status,
2993 DATA_BLOB body, DATA_BLOB *dyn,
2994 const char *location)
2996 uint8_t *outhdr;
2997 struct iovec *outbody_v;
2998 struct iovec *outdyn_v;
2999 uint32_t next_command_ofs;
3001 DEBUG(10,("smbd_smb2_request_done_ex: "
3002 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3003 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3004 dyn ? "yes": "no",
3005 (unsigned int)(dyn ? dyn->length : 0),
3006 location));
3008 if (body.length < 2) {
3009 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3012 if ((body.length % 2) != 0) {
3013 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3016 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3017 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3018 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3020 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3021 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3023 outbody_v->iov_base = (void *)body.data;
3024 outbody_v->iov_len = body.length;
3026 if (dyn) {
3027 outdyn_v->iov_base = (void *)dyn->data;
3028 outdyn_v->iov_len = dyn->length;
3029 } else {
3030 outdyn_v->iov_base = NULL;
3031 outdyn_v->iov_len = 0;
3035 * See if we need to recalculate the offset to the next response
3037 * Note that all responses may require padding (including the very last
3038 * one).
3040 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3041 next_command_ofs = SMB2_HDR_BODY;
3042 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3043 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3046 if ((next_command_ofs % 8) != 0) {
3047 size_t pad_size = 8 - (next_command_ofs % 8);
3048 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3050 * if the dyn buffer is empty
3051 * we can use it to add padding
3053 uint8_t *pad;
3055 pad = talloc_zero_array(req,
3056 uint8_t, pad_size);
3057 if (pad == NULL) {
3058 return smbd_smb2_request_error(req,
3059 NT_STATUS_NO_MEMORY);
3062 outdyn_v->iov_base = (void *)pad;
3063 outdyn_v->iov_len = pad_size;
3064 } else {
3066 * For now we copy the dynamic buffer
3067 * and add the padding to the new buffer
3069 size_t old_size;
3070 uint8_t *old_dyn;
3071 size_t new_size;
3072 uint8_t *new_dyn;
3074 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3075 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3077 new_size = old_size + pad_size;
3078 new_dyn = talloc_zero_array(req,
3079 uint8_t, new_size);
3080 if (new_dyn == NULL) {
3081 return smbd_smb2_request_error(req,
3082 NT_STATUS_NO_MEMORY);
3085 memcpy(new_dyn, old_dyn, old_size);
3086 memset(new_dyn + old_size, 0, pad_size);
3088 outdyn_v->iov_base = (void *)new_dyn;
3089 outdyn_v->iov_len = new_size;
3091 next_command_ofs += pad_size;
3094 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3095 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3096 } else {
3097 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3099 return smbd_smb2_request_reply(req);
3102 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3103 NTSTATUS status,
3104 DATA_BLOB *info,
3105 const char *location)
3107 struct smbXsrv_connection *xconn = req->xconn;
3108 DATA_BLOB body;
3109 DATA_BLOB _dyn;
3110 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3111 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3113 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3114 "at %s\n", req->current_idx, nt_errstr(status),
3115 info ? " +info" : "", location);
3117 if (unread_bytes) {
3118 /* Recvfile error. Drain incoming socket. */
3119 size_t ret;
3121 errno = 0;
3122 ret = drain_socket(xconn->transport.sock, unread_bytes);
3123 if (ret != unread_bytes) {
3124 NTSTATUS error;
3126 if (errno == 0) {
3127 error = NT_STATUS_IO_DEVICE_ERROR;
3128 } else {
3129 error = map_nt_error_from_unix_common(errno);
3132 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3133 "ret[%u] errno[%d] => %s\n",
3134 (unsigned)unread_bytes,
3135 (unsigned)ret, errno, nt_errstr(error)));
3136 return error;
3140 body.data = outhdr + SMB2_HDR_BODY;
3141 body.length = 8;
3142 SSVAL(body.data, 0, 9);
3144 if (info) {
3145 SIVAL(body.data, 0x04, info->length);
3146 } else {
3147 /* Allocated size of req->out.vector[i].iov_base
3148 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3149 * 1 byte without having to do an alloc.
3151 info = &_dyn;
3152 info->data = ((uint8_t *)outhdr) +
3153 OUTVEC_ALLOC_SIZE - 1;
3154 info->length = 1;
3155 SCVAL(info->data, 0, 0);
3159 * Note: Even if there is an error, continue to process the request.
3160 * per MS-SMB2.
3163 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3167 struct smbd_smb2_send_break_state {
3168 struct smbd_smb2_send_queue queue_entry;
3169 uint8_t nbt_hdr[NBT_HDR_SIZE];
3170 uint8_t tf[SMB2_TF_HDR_SIZE];
3171 uint8_t hdr[SMB2_HDR_BODY];
3172 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3173 uint8_t body[1];
3176 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3177 struct smbXsrv_session *session,
3178 struct smbXsrv_tcon *tcon,
3179 const uint8_t *body,
3180 size_t body_len)
3182 struct smbd_smb2_send_break_state *state;
3183 bool do_encryption = false;
3184 uint64_t session_wire_id = 0;
3185 uint64_t nonce_high = 0;
3186 uint64_t nonce_low = 0;
3187 NTSTATUS status;
3188 size_t statelen;
3189 bool ok;
3191 if (session != NULL) {
3192 session_wire_id = session->global->session_wire_id;
3193 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3194 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3195 do_encryption = true;
3199 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3200 body_len;
3202 state = talloc_zero_size(xconn, statelen);
3203 if (state == NULL) {
3204 return NT_STATUS_NO_MEMORY;
3206 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3208 if (do_encryption) {
3209 status = smb2_get_new_nonce(session,
3210 &nonce_high,
3211 &nonce_low);
3212 if (!NT_STATUS_IS_OK(status)) {
3213 return status;
3217 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3218 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3219 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3220 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3222 SIVAL(state->hdr, 0, SMB2_MAGIC);
3223 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3224 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3225 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3226 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3227 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3228 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3229 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3230 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3231 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3232 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3233 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3234 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3236 state->vector[0] = (struct iovec) {
3237 .iov_base = state->nbt_hdr,
3238 .iov_len = sizeof(state->nbt_hdr)
3241 if (do_encryption) {
3242 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3243 .iov_base = state->tf,
3244 .iov_len = sizeof(state->tf)
3246 } else {
3247 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3248 .iov_base = NULL,
3249 .iov_len = 0
3253 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3254 .iov_base = state->hdr,
3255 .iov_len = sizeof(state->hdr)
3258 memcpy(state->body, body, body_len);
3260 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3261 .iov_base = state->body,
3262 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3266 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3269 ok = smb2_setup_nbt_length(state->vector,
3270 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3271 if (!ok) {
3272 return NT_STATUS_INVALID_PARAMETER_MIX;
3275 if (do_encryption) {
3276 DATA_BLOB encryption_key = session->global->encryption_key;
3278 status = smb2_signing_encrypt_pdu(encryption_key,
3279 xconn->smb2.server.cipher,
3280 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3281 SMBD_SMB2_NUM_IOV_PER_REQ);
3282 if (!NT_STATUS_IS_OK(status)) {
3283 return status;
3287 state->queue_entry.mem_ctx = state;
3288 state->queue_entry.vector = state->vector;
3289 state->queue_entry.count = ARRAY_SIZE(state->vector);
3290 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3291 xconn->smb2.send_queue_len++;
3293 status = smbd_smb2_flush_send_queue(xconn);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 return status;
3298 return NT_STATUS_OK;
3301 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3302 struct smbXsrv_session *session,
3303 struct smbXsrv_tcon *tcon,
3304 struct smbXsrv_open *op,
3305 uint8_t oplock_level)
3307 uint8_t body[0x18];
3309 SSVAL(body, 0x00, sizeof(body));
3310 SCVAL(body, 0x02, oplock_level);
3311 SCVAL(body, 0x03, 0); /* reserved */
3312 SIVAL(body, 0x04, 0); /* reserved */
3313 SBVAL(body, 0x08, op->global->open_persistent_id);
3314 SBVAL(body, 0x10, op->global->open_volatile_id);
3316 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3319 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3320 uint16_t new_epoch,
3321 uint32_t lease_flags,
3322 struct smb2_lease_key *lease_key,
3323 uint32_t current_lease_state,
3324 uint32_t new_lease_state)
3326 uint8_t body[0x2c];
3328 SSVAL(body, 0x00, sizeof(body));
3329 SSVAL(body, 0x02, new_epoch);
3330 SIVAL(body, 0x04, lease_flags);
3331 SBVAL(body, 0x08, lease_key->data[0]);
3332 SBVAL(body, 0x10, lease_key->data[1]);
3333 SIVAL(body, 0x18, current_lease_state);
3334 SIVAL(body, 0x1c, new_lease_state);
3335 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3336 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3337 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3339 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3342 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3344 NTSTATUS status;
3345 uint32_t flags;
3346 uint64_t file_id_persistent;
3347 uint64_t file_id_volatile;
3348 struct smbXsrv_open *op = NULL;
3349 struct files_struct *fsp = NULL;
3350 const uint8_t *body = NULL;
3353 * This is only called with a pktbuf
3354 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3355 * bytes
3358 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3359 /* Transform header. Cannot recvfile. */
3360 return false;
3362 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3363 /* Not SMB2. Normal error path will cope. */
3364 return false;
3366 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3367 /* Not SMB2. Normal error path will cope. */
3368 return false;
3370 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3371 /* Needs to be a WRITE. */
3372 return false;
3374 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3375 /* Chained. Cannot recvfile. */
3376 return false;
3378 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3379 if (flags & SMB2_HDR_FLAG_CHAINED) {
3380 /* Chained. Cannot recvfile. */
3381 return false;
3383 if (flags & SMB2_HDR_FLAG_SIGNED) {
3384 /* Signed. Cannot recvfile. */
3385 return false;
3388 body = &state->pktbuf[SMB2_HDR_BODY];
3390 file_id_persistent = BVAL(body, 0x10);
3391 file_id_volatile = BVAL(body, 0x18);
3393 status = smb2srv_open_lookup(state->req->xconn,
3394 file_id_persistent,
3395 file_id_volatile,
3396 0, /* now */
3397 &op);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 return false;
3402 fsp = op->compat;
3403 if (fsp == NULL) {
3404 return false;
3406 if (fsp->conn == NULL) {
3407 return false;
3410 if (IS_IPC(fsp->conn)) {
3411 return false;
3413 if (IS_PRINT(fsp->conn)) {
3414 return false;
3417 DEBUG(10,("Doing recvfile write len = %u\n",
3418 (unsigned int)(state->pktfull - state->pktlen)));
3420 return true;
3423 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3425 struct smbd_server_connection *sconn = xconn->client->sconn;
3426 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3427 size_t max_send_queue_len;
3428 size_t cur_send_queue_len;
3430 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3432 * we're not supposed to do any io
3434 return NT_STATUS_OK;
3437 if (state->req != NULL) {
3439 * if there is already a tstream_readv_pdu
3440 * pending, we are done.
3442 return NT_STATUS_OK;
3445 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3446 cur_send_queue_len = xconn->smb2.send_queue_len;
3448 if (cur_send_queue_len > max_send_queue_len) {
3450 * if we have a lot of requests to send,
3451 * we wait until they are on the wire until we
3452 * ask for the next request.
3454 return NT_STATUS_OK;
3457 /* ask for the next request */
3458 ZERO_STRUCTP(state);
3459 state->req = smbd_smb2_request_allocate(xconn);
3460 if (state->req == NULL) {
3461 return NT_STATUS_NO_MEMORY;
3463 state->req->sconn = sconn;
3464 state->req->xconn = xconn;
3465 state->min_recv_size = lp_min_receive_file_size();
3467 TEVENT_FD_READABLE(xconn->transport.fde);
3469 return NT_STATUS_OK;
3472 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3473 uint64_t expected_seq_low,
3474 const uint8_t *inpdu, size_t size)
3476 struct smbd_server_connection *sconn = xconn->client->sconn;
3477 NTSTATUS status;
3478 struct smbd_smb2_request *req = NULL;
3480 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3481 (unsigned int)size));
3483 status = smbd_initialize_smb2(xconn, expected_seq_low);
3484 if (!NT_STATUS_IS_OK(status)) {
3485 smbd_server_connection_terminate(xconn, nt_errstr(status));
3486 return;
3489 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3490 if (!NT_STATUS_IS_OK(status)) {
3491 smbd_server_connection_terminate(xconn, nt_errstr(status));
3492 return;
3495 status = smbd_smb2_request_validate(req);
3496 if (!NT_STATUS_IS_OK(status)) {
3497 smbd_server_connection_terminate(xconn, nt_errstr(status));
3498 return;
3501 status = smbd_smb2_request_setup_out(req);
3502 if (!NT_STATUS_IS_OK(status)) {
3503 smbd_server_connection_terminate(xconn, nt_errstr(status));
3504 return;
3507 #ifdef WITH_PROFILE
3509 * this was already counted at the SMB1 layer =>
3510 * smbd_smb2_request_dispatch() should not count it twice.
3512 if (profile_p->values.request_stats.count > 0) {
3513 profile_p->values.request_stats.count--;
3515 #endif
3516 status = smbd_smb2_request_dispatch(req);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 smbd_server_connection_terminate(xconn, nt_errstr(status));
3519 return;
3522 status = smbd_smb2_request_next_incoming(xconn);
3523 if (!NT_STATUS_IS_OK(status)) {
3524 smbd_server_connection_terminate(xconn, nt_errstr(status));
3525 return;
3528 sconn->num_requests++;
3531 static int socket_error_from_errno(int ret,
3532 int sys_errno,
3533 bool *retry)
3535 *retry = false;
3537 if (ret >= 0) {
3538 return 0;
3541 if (ret != -1) {
3542 return EIO;
3545 if (sys_errno == 0) {
3546 return EIO;
3549 if (sys_errno == EINTR) {
3550 *retry = true;
3551 return sys_errno;
3554 if (sys_errno == EINPROGRESS) {
3555 *retry = true;
3556 return sys_errno;
3559 if (sys_errno == EAGAIN) {
3560 *retry = true;
3561 return sys_errno;
3564 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3565 if (sys_errno == ENOMEM) {
3566 *retry = true;
3567 return sys_errno;
3570 #ifdef EWOULDBLOCK
3571 #if EWOULDBLOCK != EAGAIN
3572 if (sys_errno == EWOULDBLOCK) {
3573 *retry = true;
3574 return sys_errno;
3576 #endif
3577 #endif
3579 return sys_errno;
3582 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3584 int ret;
3585 int err;
3586 bool retry;
3587 NTSTATUS status;
3589 if (xconn->smb2.send_queue == NULL) {
3590 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3591 return NT_STATUS_OK;
3594 while (xconn->smb2.send_queue != NULL) {
3595 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3596 bool ok;
3598 if (e->sendfile_header != NULL) {
3599 size_t size = 0;
3600 size_t i = 0;
3601 uint8_t *buf;
3603 status = NT_STATUS_INTERNAL_ERROR;
3605 for (i=0; i < e->count; i++) {
3606 size += e->vector[i].iov_len;
3609 if (size <= e->sendfile_header->length) {
3610 buf = e->sendfile_header->data;
3611 } else {
3612 buf = talloc_array(e->mem_ctx, uint8_t, size);
3613 if (buf == NULL) {
3614 return NT_STATUS_NO_MEMORY;
3618 size = 0;
3619 for (i=0; i < e->count; i++) {
3620 memcpy(buf+size,
3621 e->vector[i].iov_base,
3622 e->vector[i].iov_len);
3623 size += e->vector[i].iov_len;
3626 e->sendfile_header->data = buf;
3627 e->sendfile_header->length = size;
3628 e->sendfile_status = &status;
3629 e->count = 0;
3631 xconn->smb2.send_queue_len--;
3632 DLIST_REMOVE(xconn->smb2.send_queue, e);
3634 * This triggers the sendfile path via
3635 * the destructor.
3637 talloc_free(e->mem_ctx);
3639 if (!NT_STATUS_IS_OK(status)) {
3640 return status;
3642 continue;
3645 ret = writev(xconn->transport.sock, e->vector, e->count);
3646 if (ret == 0) {
3647 /* propagate end of file */
3648 return NT_STATUS_INTERNAL_ERROR;
3650 err = socket_error_from_errno(ret, errno, &retry);
3651 if (retry) {
3652 /* retry later */
3653 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3654 return NT_STATUS_OK;
3656 if (err != 0) {
3657 return map_nt_error_from_unix_common(err);
3660 ok = iov_advance(&e->vector, &e->count, ret);
3661 if (!ok) {
3662 return NT_STATUS_INTERNAL_ERROR;
3665 if (e->count > 0) {
3666 /* we have more to write */
3667 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3668 return NT_STATUS_OK;
3671 xconn->smb2.send_queue_len--;
3672 DLIST_REMOVE(xconn->smb2.send_queue, e);
3673 talloc_free(e->mem_ctx);
3677 * Restart reads if we were blocked on
3678 * draining the send queue.
3681 status = smbd_smb2_request_next_incoming(xconn);
3682 if (!NT_STATUS_IS_OK(status)) {
3683 return status;
3686 return NT_STATUS_OK;
3689 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3690 uint16_t fde_flags)
3692 struct smbd_server_connection *sconn = xconn->client->sconn;
3693 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3694 struct smbd_smb2_request *req = NULL;
3695 size_t min_recvfile_size = UINT32_MAX;
3696 int ret;
3697 int err;
3698 bool retry;
3699 NTSTATUS status;
3700 NTTIME now;
3702 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3704 * we're not supposed to do any io
3706 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3707 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3708 return NT_STATUS_OK;
3711 if (fde_flags & TEVENT_FD_WRITE) {
3712 status = smbd_smb2_flush_send_queue(xconn);
3713 if (!NT_STATUS_IS_OK(status)) {
3714 return status;
3718 if (!(fde_flags & TEVENT_FD_READ)) {
3719 return NT_STATUS_OK;
3722 if (state->req == NULL) {
3723 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3724 return NT_STATUS_OK;
3727 again:
3728 if (!state->hdr.done) {
3729 state->hdr.done = true;
3731 state->vector.iov_base = (void *)state->hdr.nbt;
3732 state->vector.iov_len = NBT_HDR_SIZE;
3735 ret = readv(xconn->transport.sock, &state->vector, 1);
3736 if (ret == 0) {
3737 /* propagate end of file */
3738 return NT_STATUS_END_OF_FILE;
3740 err = socket_error_from_errno(ret, errno, &retry);
3741 if (retry) {
3742 /* retry later */
3743 TEVENT_FD_READABLE(xconn->transport.fde);
3744 return NT_STATUS_OK;
3746 if (err != 0) {
3747 return map_nt_error_from_unix_common(err);
3750 if (ret < state->vector.iov_len) {
3751 uint8_t *base;
3752 base = (uint8_t *)state->vector.iov_base;
3753 base += ret;
3754 state->vector.iov_base = (void *)base;
3755 state->vector.iov_len -= ret;
3756 /* we have more to read */
3757 TEVENT_FD_READABLE(xconn->transport.fde);
3758 return NT_STATUS_OK;
3761 if (state->pktlen > 0) {
3762 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3764 * Not a possible receivefile write.
3765 * Read the rest of the data.
3767 state->doing_receivefile = false;
3769 state->pktbuf = talloc_realloc(state->req,
3770 state->pktbuf,
3771 uint8_t,
3772 state->pktfull);
3773 if (state->pktbuf == NULL) {
3774 return NT_STATUS_NO_MEMORY;
3777 state->vector.iov_base = (void *)(state->pktbuf +
3778 state->pktlen);
3779 state->vector.iov_len = (state->pktfull -
3780 state->pktlen);
3782 state->pktlen = state->pktfull;
3783 goto again;
3787 * Either this is a receivefile write so we've
3788 * done a short read, or if not we have all the data.
3790 goto got_full;
3794 * Now we analyze the NBT header
3796 if (state->hdr.nbt[0] != 0x00) {
3797 state->min_recv_size = 0;
3799 state->pktfull = smb2_len(state->hdr.nbt);
3800 if (state->pktfull == 0) {
3801 goto got_full;
3804 if (state->min_recv_size != 0) {
3805 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3806 min_recvfile_size += state->min_recv_size;
3809 if (state->pktfull > min_recvfile_size) {
3811 * Might be a receivefile write. Read the SMB2 HEADER +
3812 * SMB2_WRITE header first. Set 'doing_receivefile'
3813 * as we're *attempting* receivefile write. If this
3814 * turns out not to be a SMB2_WRITE request or otherwise
3815 * not suitable then we'll just read the rest of the data
3816 * the next time this function is called.
3818 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3819 state->doing_receivefile = true;
3820 } else {
3821 state->pktlen = state->pktfull;
3824 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3825 if (state->pktbuf == NULL) {
3826 return NT_STATUS_NO_MEMORY;
3829 state->vector.iov_base = (void *)state->pktbuf;
3830 state->vector.iov_len = state->pktlen;
3832 goto again;
3834 got_full:
3836 if (state->hdr.nbt[0] != 0x00) {
3837 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3838 state->hdr.nbt[0]));
3840 req = state->req;
3841 ZERO_STRUCTP(state);
3842 state->req = req;
3843 state->min_recv_size = lp_min_receive_file_size();
3844 req = NULL;
3845 goto again;
3848 req = state->req;
3849 state->req = NULL;
3851 req->request_time = timeval_current();
3852 now = timeval_to_nttime(&req->request_time);
3854 status = smbd_smb2_inbuf_parse_compound(xconn,
3855 now,
3856 state->pktbuf,
3857 state->pktlen,
3858 req,
3859 &req->in.vector,
3860 &req->in.vector_count);
3861 if (!NT_STATUS_IS_OK(status)) {
3862 return status;
3865 if (state->doing_receivefile) {
3866 req->smb1req = talloc_zero(req, struct smb_request);
3867 if (req->smb1req == NULL) {
3868 return NT_STATUS_NO_MEMORY;
3870 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3873 ZERO_STRUCTP(state);
3875 req->current_idx = 1;
3877 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3878 req->current_idx, req->in.vector_count));
3880 status = smbd_smb2_request_validate(req);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 return status;
3885 status = smbd_smb2_request_setup_out(req);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 return status;
3890 status = smbd_smb2_request_dispatch(req);
3891 if (!NT_STATUS_IS_OK(status)) {
3892 return status;
3895 sconn->num_requests++;
3897 /* The timeout_processing function isn't run nearly
3898 often enough to implement 'max log size' without
3899 overrunning the size of the file by many megabytes.
3900 This is especially true if we are running at debug
3901 level 10. Checking every 50 SMB2s is a nice
3902 tradeoff of performance vs log file size overrun. */
3904 if ((sconn->num_requests % 50) == 0 &&
3905 need_to_check_log_size()) {
3906 change_to_root_user();
3907 check_log_size();
3910 status = smbd_smb2_request_next_incoming(xconn);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 return status;
3915 return NT_STATUS_OK;
3918 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3919 struct tevent_fd *fde,
3920 uint16_t flags,
3921 void *private_data)
3923 struct smbXsrv_connection *xconn =
3924 talloc_get_type_abort(private_data,
3925 struct smbXsrv_connection);
3926 NTSTATUS status;
3928 status = smbd_smb2_io_handler(xconn, flags);
3929 if (!NT_STATUS_IS_OK(status)) {
3930 smbd_server_connection_terminate(xconn, nt_errstr(status));
3931 return;