smbd: Fix a typo
[Samba.git] / source3 / smbd / smb2_server.c
blob565f9996245f9605f04b8da7631cf943b781ba84
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "lib/util/iov_buf.h"
32 #include "auth.h"
33 #include "lib/crypto/sha512.h"
35 static void smbd_smb2_connection_handler(struct tevent_context *ev,
36 struct tevent_fd *fde,
37 uint16_t flags,
38 void *private_data);
39 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
41 static const struct smbd_smb2_dispatch_table {
42 uint16_t opcode;
43 const char *name;
44 bool need_session;
45 bool need_tcon;
46 bool as_root;
47 uint16_t fileid_ofs;
48 bool allow_invalid_fileid;
49 bool modify;
50 } smbd_smb2_table[] = {
51 #define _OP(o) .opcode = o, .name = #o
53 _OP(SMB2_OP_NEGPROT),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_SESSSETUP),
57 .as_root = true,
58 },{
59 _OP(SMB2_OP_LOGOFF),
60 .need_session = true,
61 .as_root = true,
62 },{
63 _OP(SMB2_OP_TCON),
64 .need_session = true,
66 * This call needs to be run as root.
68 * smbd_smb2_request_process_tcon()
69 * calls make_connection_snum(), which will call
70 * change_to_user(), when needed.
72 .as_root = true,
73 },{
74 _OP(SMB2_OP_TDIS),
75 .need_session = true,
76 .need_tcon = true,
77 .as_root = true,
78 },{
79 _OP(SMB2_OP_CREATE),
80 .need_session = true,
81 .need_tcon = true,
82 },{
83 _OP(SMB2_OP_CLOSE),
84 .need_session = true,
85 .need_tcon = true,
86 .fileid_ofs = 0x08,
87 },{
88 _OP(SMB2_OP_FLUSH),
89 .need_session = true,
90 .need_tcon = true,
91 .fileid_ofs = 0x08,
92 },{
93 _OP(SMB2_OP_READ),
94 .need_session = true,
95 .need_tcon = true,
96 .fileid_ofs = 0x10,
97 },{
98 _OP(SMB2_OP_WRITE),
99 .need_session = true,
100 .need_tcon = true,
101 .fileid_ofs = 0x10,
102 .modify = true,
104 _OP(SMB2_OP_LOCK),
105 .need_session = true,
106 .need_tcon = true,
107 .fileid_ofs = 0x08,
109 _OP(SMB2_OP_IOCTL),
110 .need_session = true,
111 .need_tcon = true,
112 .fileid_ofs = 0x08,
113 .allow_invalid_fileid = true,
114 .modify = true,
116 _OP(SMB2_OP_CANCEL),
117 .as_root = true,
119 _OP(SMB2_OP_KEEPALIVE),
120 .as_root = true,
122 _OP(SMB2_OP_QUERY_DIRECTORY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_NOTIFY),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x08,
132 _OP(SMB2_OP_GETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x18,
137 _OP(SMB2_OP_SETINFO),
138 .need_session = true,
139 .need_tcon = true,
140 .fileid_ofs = 0x10,
141 .modify = true,
143 _OP(SMB2_OP_BREAK),
144 .need_session = true,
145 .need_tcon = true,
147 * we do not set
148 * .fileid_ofs here
149 * as LEASE breaks does not
150 * have a file id
155 const char *smb2_opcode_name(uint16_t opcode)
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return "Bad SMB2 opcode";
160 return smbd_smb2_table[opcode].name;
163 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
165 const struct smbd_smb2_dispatch_table *ret = NULL;
167 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
168 return NULL;
171 ret = &smbd_smb2_table[opcode];
173 SMB_ASSERT(ret->opcode == opcode);
175 return ret;
178 static void print_req_vectors(const struct smbd_smb2_request *req)
180 int i;
182 for (i = 0; i < req->in.vector_count; i++) {
183 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
184 (unsigned int)i,
185 (unsigned int)req->in.vector[i].iov_len);
187 for (i = 0; i < req->out.vector_count; i++) {
188 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
189 (unsigned int)i,
190 (unsigned int)req->out.vector[i].iov_len);
194 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
196 if (size < (4 + SMB2_HDR_BODY)) {
197 return false;
200 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
201 return false;
204 return true;
207 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
209 return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
212 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
213 uint64_t expected_seq_low)
215 TALLOC_FREE(xconn->transport.fde);
217 xconn->smb2.credits.seq_low = expected_seq_low;
218 xconn->smb2.credits.seq_range = 1;
219 xconn->smb2.credits.granted = 1;
220 xconn->smb2.credits.max = lp_smb2_max_credits();
221 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
222 xconn->smb2.credits.max);
223 if (xconn->smb2.credits.bitmap == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
228 xconn,
229 xconn->transport.sock,
230 TEVENT_FD_READ,
231 smbd_smb2_connection_handler,
232 xconn);
233 if (xconn->transport.fde == NULL) {
234 return NT_STATUS_NO_MEMORY;
237 /* Ensure child is set to non-blocking mode */
238 set_blocking(xconn->transport.sock, false);
239 return NT_STATUS_OK;
242 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
243 #define _smb2_setlen(_buf,len) do { \
244 uint8_t *buf = (uint8_t *)_buf; \
245 buf[0] = 0; \
246 buf[1] = ((len)&0xFF0000)>>16; \
247 buf[2] = ((len)&0xFF00)>>8; \
248 buf[3] = (len)&0xFF; \
249 } while (0)
251 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
253 ssize_t len;
255 if (count == 0) {
256 return false;
259 len = iov_buflen(vector+1, count-1);
261 if ((len == -1) || (len > 0xFFFFFF)) {
262 return false;
265 _smb2_setlen(vector[0].iov_base, len);
266 return true;
269 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
271 if (req->first_key.length > 0) {
272 data_blob_clear_free(&req->first_key);
274 if (req->last_key.length > 0) {
275 data_blob_clear_free(&req->last_key);
277 return 0;
280 void smb2_request_set_async_internal(struct smbd_smb2_request *req,
281 bool async_internal)
283 req->async_internal = async_internal;
286 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
288 TALLOC_CTX *mem_pool;
289 struct smbd_smb2_request *req;
291 #if 0
292 /* Enable this to find subtle valgrind errors. */
293 mem_pool = talloc_init("smbd_smb2_request_allocate");
294 #else
295 mem_pool = talloc_tos();
296 #endif
297 if (mem_pool == NULL) {
298 return NULL;
301 req = talloc_zero(mem_pool, struct smbd_smb2_request);
302 if (req == NULL) {
303 talloc_free(mem_pool);
304 return NULL;
306 talloc_reparent(mem_pool, mem_ctx, req);
307 #if 0
308 TALLOC_FREE(mem_pool);
309 #endif
311 req->last_session_id = UINT64_MAX;
312 req->last_tid = UINT32_MAX;
314 talloc_set_destructor(req, smbd_smb2_request_destructor);
316 return req;
319 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
320 NTTIME now,
321 uint8_t *buf,
322 size_t buflen,
323 struct smbd_smb2_request *req,
324 struct iovec **piov,
325 int *pnum_iov)
327 TALLOC_CTX *mem_ctx = req;
328 struct iovec *iov;
329 int num_iov = 1;
330 size_t taken = 0;
331 uint8_t *first_hdr = buf;
332 size_t verified_buflen = 0;
333 uint8_t *tf = NULL;
334 size_t tf_len = 0;
337 * Note: index '0' is reserved for the transport protocol
339 iov = req->in._vector;
341 while (taken < buflen) {
342 size_t len = buflen - taken;
343 uint8_t *hdr = first_hdr + taken;
344 struct iovec *cur;
345 size_t full_size;
346 size_t next_command_ofs;
347 uint16_t body_size;
348 uint8_t *body = NULL;
349 uint32_t dyn_size;
350 uint8_t *dyn = NULL;
351 struct iovec *iov_alloc = NULL;
353 if (iov != req->in._vector) {
354 iov_alloc = iov;
357 if (verified_buflen > taken) {
358 len = verified_buflen - taken;
359 } else {
360 tf = NULL;
361 tf_len = 0;
364 if (len < 4) {
365 DEBUG(10, ("%d bytes left, expected at least %d\n",
366 (int)len, 4));
367 goto inval;
369 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
370 struct smbXsrv_session *s = NULL;
371 uint64_t uid;
372 struct iovec tf_iov[2];
373 NTSTATUS status;
374 size_t enc_len;
376 if (xconn->protocol < PROTOCOL_SMB2_24) {
377 DEBUG(10, ("Got SMB2_TRANSFORM header, "
378 "but dialect[0x%04X] is used\n",
379 xconn->smb2.server.dialect));
380 goto inval;
383 if (xconn->smb2.server.cipher == 0) {
384 DEBUG(10, ("Got SMB2_TRANSFORM header, "
385 "but not negotiated "
386 "client[0x%08X] server[0x%08X]\n",
387 xconn->smb2.client.capabilities,
388 xconn->smb2.server.capabilities));
389 goto inval;
392 if (len < SMB2_TF_HDR_SIZE) {
393 DEBUG(1, ("%d bytes left, expected at least %d\n",
394 (int)len, SMB2_TF_HDR_SIZE));
395 goto inval;
397 tf = hdr;
398 tf_len = SMB2_TF_HDR_SIZE;
399 taken += tf_len;
401 hdr = first_hdr + taken;
402 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
403 uid = BVAL(tf, SMB2_TF_SESSION_ID);
405 if (len < SMB2_TF_HDR_SIZE + enc_len) {
406 DEBUG(1, ("%d bytes left, expected at least %d\n",
407 (int)len,
408 (int)(SMB2_TF_HDR_SIZE + enc_len)));
409 goto inval;
412 status = smb2srv_session_lookup_conn(xconn, uid, now,
413 &s);
414 if (s == NULL) {
415 DEBUG(1, ("invalid session[%llu] in "
416 "SMB2_TRANSFORM header\n",
417 (unsigned long long)uid));
418 TALLOC_FREE(iov_alloc);
419 return NT_STATUS_USER_SESSION_DELETED;
422 tf_iov[0].iov_base = (void *)tf;
423 tf_iov[0].iov_len = tf_len;
424 tf_iov[1].iov_base = (void *)hdr;
425 tf_iov[1].iov_len = enc_len;
427 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
428 xconn->smb2.server.cipher,
429 tf_iov, 2);
430 if (!NT_STATUS_IS_OK(status)) {
431 TALLOC_FREE(iov_alloc);
432 return status;
435 verified_buflen = taken + enc_len;
436 len = enc_len;
440 * We need the header plus the body length field
443 if (len < SMB2_HDR_BODY + 2) {
444 DEBUG(10, ("%d bytes left, expected at least %d\n",
445 (int)len, SMB2_HDR_BODY));
446 goto inval;
448 if (IVAL(hdr, 0) != SMB2_MAGIC) {
449 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
450 IVAL(hdr, 0)));
451 goto inval;
453 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
454 DEBUG(10, ("Got HDR len %d, expected %d\n",
455 SVAL(hdr, 4), SMB2_HDR_BODY));
456 goto inval;
459 full_size = len;
460 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
461 body_size = SVAL(hdr, SMB2_HDR_BODY);
463 if (next_command_ofs != 0) {
464 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
465 goto inval;
467 if (next_command_ofs > full_size) {
468 goto inval;
470 full_size = next_command_ofs;
472 if (body_size < 2) {
473 goto inval;
475 body_size &= 0xfffe;
477 if (body_size > (full_size - SMB2_HDR_BODY)) {
479 * let the caller handle the error
481 body_size = full_size - SMB2_HDR_BODY;
483 body = hdr + SMB2_HDR_BODY;
484 dyn = body + body_size;
485 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
487 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
488 struct iovec *iov_tmp = NULL;
490 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
491 struct iovec,
492 num_iov +
493 SMBD_SMB2_NUM_IOV_PER_REQ);
494 if (iov_tmp == NULL) {
495 TALLOC_FREE(iov_alloc);
496 return NT_STATUS_NO_MEMORY;
499 if (iov_alloc == NULL) {
500 memcpy(iov_tmp,
501 req->in._vector,
502 sizeof(req->in._vector));
505 iov = iov_tmp;
507 cur = &iov[num_iov];
508 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
510 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
511 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
512 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
513 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
514 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
515 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
516 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
517 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
519 taken += full_size;
522 *piov = iov;
523 *pnum_iov = num_iov;
524 return NT_STATUS_OK;
526 inval:
527 if (iov != req->in._vector) {
528 TALLOC_FREE(iov);
530 return NT_STATUS_INVALID_PARAMETER;
533 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
534 const uint8_t *_inpdu, size_t size,
535 struct smbd_smb2_request **_req)
537 struct smbd_server_connection *sconn = xconn->client->sconn;
538 struct smbd_smb2_request *req;
539 uint32_t protocol_version;
540 uint8_t *inpdu = NULL;
541 const uint8_t *inhdr = NULL;
542 uint16_t cmd;
543 uint32_t next_command_ofs;
544 NTSTATUS status;
545 NTTIME now;
547 if (size < (SMB2_HDR_BODY + 2)) {
548 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
549 return NT_STATUS_INVALID_PARAMETER;
552 inhdr = _inpdu;
554 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
555 if (protocol_version != SMB2_MAGIC) {
556 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
557 protocol_version));
558 return NT_STATUS_INVALID_PARAMETER;
561 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
562 if (cmd != SMB2_OP_NEGPROT) {
563 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
564 cmd));
565 return NT_STATUS_INVALID_PARAMETER;
568 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
569 if (next_command_ofs != 0) {
570 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
571 next_command_ofs));
572 return NT_STATUS_INVALID_PARAMETER;
575 req = smbd_smb2_request_allocate(xconn);
576 if (req == NULL) {
577 return NT_STATUS_NO_MEMORY;
579 req->sconn = sconn;
580 req->xconn = xconn;
582 inpdu = talloc_memdup(req, _inpdu, size);
583 if (inpdu == NULL) {
584 return NT_STATUS_NO_MEMORY;
587 req->request_time = timeval_current();
588 now = timeval_to_nttime(&req->request_time);
590 status = smbd_smb2_inbuf_parse_compound(xconn,
591 now,
592 inpdu,
593 size,
594 req, &req->in.vector,
595 &req->in.vector_count);
596 if (!NT_STATUS_IS_OK(status)) {
597 TALLOC_FREE(req);
598 return status;
601 req->current_idx = 1;
603 *_req = req;
604 return NT_STATUS_OK;
607 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
608 uint64_t message_id, uint64_t seq_id)
610 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
611 unsigned int offset;
612 uint64_t seq_tmp;
614 seq_tmp = xconn->smb2.credits.seq_low;
615 if (seq_id < seq_tmp) {
616 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
617 "%llu (sequence id %llu) "
618 "(granted = %u, low = %llu, range = %u)\n",
619 (unsigned long long)message_id,
620 (unsigned long long)seq_id,
621 (unsigned int)xconn->smb2.credits.granted,
622 (unsigned long long)xconn->smb2.credits.seq_low,
623 (unsigned int)xconn->smb2.credits.seq_range));
624 return false;
627 seq_tmp += xconn->smb2.credits.seq_range;
628 if (seq_id >= seq_tmp) {
629 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
630 "%llu (sequence id %llu) "
631 "(granted = %u, low = %llu, range = %u)\n",
632 (unsigned long long)message_id,
633 (unsigned long long)seq_id,
634 (unsigned int)xconn->smb2.credits.granted,
635 (unsigned long long)xconn->smb2.credits.seq_low,
636 (unsigned int)xconn->smb2.credits.seq_range));
637 return false;
640 offset = seq_id % xconn->smb2.credits.max;
642 if (bitmap_query(credits_bm, offset)) {
643 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
644 "%llu (sequence id %llu) "
645 "(granted = %u, low = %llu, range = %u) "
646 "(bm offset %u)\n",
647 (unsigned long long)message_id,
648 (unsigned long long)seq_id,
649 (unsigned int)xconn->smb2.credits.granted,
650 (unsigned long long)xconn->smb2.credits.seq_low,
651 (unsigned int)xconn->smb2.credits.seq_range,
652 offset));
653 return false;
656 /* Mark the message_ids as seen in the bitmap. */
657 bitmap_set(credits_bm, offset);
659 if (seq_id != xconn->smb2.credits.seq_low) {
660 return true;
664 * Move the window forward by all the message_id's
665 * already seen.
667 while (bitmap_query(credits_bm, offset)) {
668 DEBUG(10,("smb2_validate_sequence_number: clearing "
669 "id %llu (position %u) from bitmap\n",
670 (unsigned long long)(xconn->smb2.credits.seq_low),
671 offset));
672 bitmap_clear(credits_bm, offset);
674 xconn->smb2.credits.seq_low += 1;
675 xconn->smb2.credits.seq_range -= 1;
676 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
679 return true;
682 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
683 const uint8_t *inhdr)
685 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
686 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
687 uint16_t credit_charge = 1;
688 uint64_t i;
690 if (opcode == SMB2_OP_CANCEL) {
691 /* SMB2_CANCEL requests by definition resend messageids. */
692 return true;
695 if (xconn->smb2.credits.multicredit) {
696 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
697 credit_charge = MAX(credit_charge, 1);
700 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
701 "credits_granted %llu, "
702 "seqnum low/range: %llu/%llu\n",
703 (unsigned long long) message_id,
704 (unsigned long long) credit_charge,
705 (unsigned long long) xconn->smb2.credits.granted,
706 (unsigned long long) xconn->smb2.credits.seq_low,
707 (unsigned long long) xconn->smb2.credits.seq_range));
709 if (xconn->smb2.credits.granted < credit_charge) {
710 DEBUG(0, ("smb2_validate_message_id: client used more "
711 "credits than granted, mid %llu, charge %llu, "
712 "credits_granted %llu, "
713 "seqnum low/range: %llu/%llu\n",
714 (unsigned long long) message_id,
715 (unsigned long long) credit_charge,
716 (unsigned long long) xconn->smb2.credits.granted,
717 (unsigned long long) xconn->smb2.credits.seq_low,
718 (unsigned long long) xconn->smb2.credits.seq_range));
719 return false;
723 * now check the message ids
725 * for multi-credit requests we need to check all current mid plus
726 * the implicit mids caused by the credit charge
727 * e.g. current mid = 15, charge 5 => mark 15-19 as used
730 for (i = 0; i <= (credit_charge-1); i++) {
731 uint64_t id = message_id + i;
732 bool ok;
734 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
735 (unsigned long long)message_id,
736 credit_charge,
737 (unsigned long long)id));
739 ok = smb2_validate_sequence_number(xconn, message_id, id);
740 if (!ok) {
741 return false;
745 /* substract used credits */
746 xconn->smb2.credits.granted -= credit_charge;
748 return true;
751 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
753 int count;
754 int idx;
756 count = req->in.vector_count;
758 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
759 /* It's not a SMB2 request */
760 return NT_STATUS_INVALID_PARAMETER;
763 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
764 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
765 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
766 const uint8_t *inhdr = NULL;
768 if (hdr->iov_len != SMB2_HDR_BODY) {
769 return NT_STATUS_INVALID_PARAMETER;
772 if (body->iov_len < 2) {
773 return NT_STATUS_INVALID_PARAMETER;
776 inhdr = (const uint8_t *)hdr->iov_base;
778 /* Check the SMB2 header */
779 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
780 return NT_STATUS_INVALID_PARAMETER;
783 if (!smb2_validate_message_id(req->xconn, inhdr)) {
784 return NT_STATUS_INVALID_PARAMETER;
788 return NT_STATUS_OK;
791 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
792 const struct iovec *in_vector,
793 struct iovec *out_vector)
795 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
796 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
797 uint16_t credit_charge = 1;
798 uint16_t credits_requested;
799 uint32_t out_flags;
800 uint16_t cmd;
801 NTSTATUS out_status;
802 uint16_t credits_granted = 0;
803 uint64_t credits_possible;
804 uint16_t current_max_credits;
807 * first we grant only 1/16th of the max range.
809 * Windows also starts with the 1/16th and then grants
810 * more later. I was only able to trigger higher
811 * values, when using a very high credit charge.
813 * TODO: scale up depending on load, free memory
814 * or other stuff.
815 * Maybe also on the relationship between number
816 * of requests and the used sequence number.
817 * Which means we would grant more credits
818 * for client which use multi credit requests.
820 current_max_credits = xconn->smb2.credits.max / 16;
821 current_max_credits = MAX(current_max_credits, 1);
823 if (xconn->smb2.credits.multicredit) {
824 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
825 credit_charge = MAX(credit_charge, 1);
828 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
829 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
830 credits_requested = MAX(credits_requested, 1);
831 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
832 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
834 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
836 if (xconn->smb2.credits.max < credit_charge) {
837 smbd_server_connection_terminate(xconn,
838 "client error: credit charge > max credits\n");
839 return;
842 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
844 * In case we already send an async interim
845 * response, we should not grant
846 * credits on the final response.
848 credits_granted = 0;
849 } else {
850 uint16_t additional_possible =
851 xconn->smb2.credits.max - credit_charge;
852 uint16_t additional_max = 0;
853 uint16_t additional_credits = credits_requested - 1;
855 switch (cmd) {
856 case SMB2_OP_NEGPROT:
857 break;
858 case SMB2_OP_SESSSETUP:
860 * Windows 2012 RC1 starts to grant
861 * additional credits
862 * with a successful session setup
864 if (NT_STATUS_IS_OK(out_status)) {
865 additional_max = 32;
867 break;
868 default:
870 * We match windows and only grant additional credits
871 * in chunks of 32.
873 additional_max = 32;
874 break;
877 additional_max = MIN(additional_max, additional_possible);
878 additional_credits = MIN(additional_credits, additional_max);
880 credits_granted = credit_charge + additional_credits;
884 * sequence numbers should not wrap
886 * 1. calculate the possible credits until
887 * the sequence numbers start to wrap on 64-bit.
889 * 2. UINT64_MAX is used for Break Notifications.
891 * 2. truncate the possible credits to the maximum
892 * credits we want to grant to the client in total.
894 * 3. remove the range we'll already granted to the client
895 * this makes sure the client consumes the lowest sequence
896 * number, before we can grant additional credits.
898 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
899 if (credits_possible > 0) {
900 /* remove UINT64_MAX */
901 credits_possible -= 1;
903 credits_possible = MIN(credits_possible, current_max_credits);
904 credits_possible -= xconn->smb2.credits.seq_range;
906 credits_granted = MIN(credits_granted, credits_possible);
908 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
909 xconn->smb2.credits.granted += credits_granted;
910 xconn->smb2.credits.seq_range += credits_granted;
912 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
913 "granted %u, current possible/max %u/%u, "
914 "total granted/max/low/range %u/%u/%llu/%u\n",
915 (unsigned int)credits_requested,
916 (unsigned int)credit_charge,
917 (unsigned int)credits_granted,
918 (unsigned int)credits_possible,
919 (unsigned int)current_max_credits,
920 (unsigned int)xconn->smb2.credits.granted,
921 (unsigned int)xconn->smb2.credits.max,
922 (unsigned long long)xconn->smb2.credits.seq_low,
923 (unsigned int)xconn->smb2.credits.seq_range));
926 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
927 struct smbd_smb2_request *outreq)
929 int count, idx;
930 uint16_t total_credits = 0;
932 count = outreq->out.vector_count;
934 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
935 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
936 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
937 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
939 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
941 /* To match Windows, count up what we
942 just granted. */
943 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
944 /* Set to zero in all but the last reply. */
945 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
946 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
947 } else {
948 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
953 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
955 if (req->current_idx <= 1) {
956 if (size <= sizeof(req->out._body)) {
957 return data_blob_const(req->out._body, size);
961 return data_blob_talloc(req, NULL, size);
964 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
966 struct smbXsrv_connection *xconn = req->xconn;
967 TALLOC_CTX *mem_ctx;
968 struct iovec *vector;
969 int count;
970 int idx;
971 bool ok;
973 count = req->in.vector_count;
974 if (count <= ARRAY_SIZE(req->out._vector)) {
975 mem_ctx = req;
976 vector = req->out._vector;
977 } else {
978 vector = talloc_zero_array(req, struct iovec, count);
979 if (vector == NULL) {
980 return NT_STATUS_NO_MEMORY;
982 mem_ctx = vector;
985 vector[0].iov_base = req->out.nbt_hdr;
986 vector[0].iov_len = 4;
987 SIVAL(req->out.nbt_hdr, 0, 0);
989 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
990 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
991 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
992 uint8_t *outhdr = NULL;
993 uint8_t *outbody = NULL;
994 uint32_t next_command_ofs = 0;
995 struct iovec *current = &vector[idx];
997 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
998 /* we have a next command -
999 * setup for the error case. */
1000 next_command_ofs = SMB2_HDR_BODY + 9;
1003 if (idx == 1) {
1004 outhdr = req->out._hdr;
1005 } else {
1006 outhdr = talloc_zero_array(mem_ctx, uint8_t,
1007 OUTVEC_ALLOC_SIZE);
1008 if (outhdr == NULL) {
1009 return NT_STATUS_NO_MEMORY;
1013 outbody = outhdr + SMB2_HDR_BODY;
1016 * SMBD_SMB2_TF_IOV_OFS might be used later
1018 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1019 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1021 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1022 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1024 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1025 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1027 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1028 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1030 /* setup the SMB2 header */
1031 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1032 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1033 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1034 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1035 SIVAL(outhdr, SMB2_HDR_STATUS,
1036 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1037 SSVAL(outhdr, SMB2_HDR_OPCODE,
1038 SVAL(inhdr, SMB2_HDR_OPCODE));
1039 SIVAL(outhdr, SMB2_HDR_FLAGS,
1040 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1041 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1042 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1043 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1044 SIVAL(outhdr, SMB2_HDR_PID,
1045 IVAL(inhdr, SMB2_HDR_PID));
1046 SIVAL(outhdr, SMB2_HDR_TID,
1047 IVAL(inhdr, SMB2_HDR_TID));
1048 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1049 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1050 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1051 inhdr + SMB2_HDR_SIGNATURE, 16);
1053 /* setup error body header */
1054 SSVAL(outbody, 0x00, 0x08 + 1);
1055 SSVAL(outbody, 0x02, 0);
1056 SIVAL(outbody, 0x04, 0);
1059 req->out.vector = vector;
1060 req->out.vector_count = count;
1062 /* setup the length of the NBT packet */
1063 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1064 if (!ok) {
1065 return NT_STATUS_INVALID_PARAMETER_MIX;
1068 DLIST_ADD_END(xconn->smb2.requests, req);
1070 return NT_STATUS_OK;
1073 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1074 const char *reason,
1075 const char *location)
1077 struct smbXsrv_client *client = xconn->client;
1079 DEBUG(10,("smbd_server_connection_terminate_ex: conn[%s] reason[%s] at %s\n",
1080 smbXsrv_connection_dbg(xconn), reason, location));
1082 if (client->connections->next != NULL) {
1083 /* TODO: cancel pending requests */
1084 DLIST_REMOVE(client->connections, xconn);
1085 TALLOC_FREE(xconn);
1086 return;
1090 * The last connection was disconnected
1092 exit_server_cleanly(reason);
1095 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1096 struct iovec *outvec,
1097 const struct iovec *srcvec)
1099 const uint8_t *srctf;
1100 size_t srctf_len;
1101 const uint8_t *srchdr;
1102 size_t srchdr_len;
1103 const uint8_t *srcbody;
1104 size_t srcbody_len;
1105 const uint8_t *expected_srcbody;
1106 const uint8_t *srcdyn;
1107 size_t srcdyn_len;
1108 const uint8_t *expected_srcdyn;
1109 uint8_t *dsttf;
1110 uint8_t *dsthdr;
1111 uint8_t *dstbody;
1112 uint8_t *dstdyn;
1114 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1115 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1116 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1117 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1118 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1119 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1120 expected_srcbody = srchdr + SMB2_HDR_BODY;
1121 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1122 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1123 expected_srcdyn = srcbody + 8;
1125 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1126 return false;
1129 if (srchdr_len != SMB2_HDR_BODY) {
1130 return false;
1133 if (srctf_len == SMB2_TF_HDR_SIZE) {
1134 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1135 if (dsttf == NULL) {
1136 return false;
1138 } else {
1139 dsttf = NULL;
1141 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1142 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1144 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1145 * be allocated with size OUTVEC_ALLOC_SIZE. */
1147 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1148 if (dsthdr == NULL) {
1149 return false;
1151 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1152 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1155 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1156 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1157 * then duplicate this. Else use talloc_memdup().
1160 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1161 dstbody = dsthdr + SMB2_HDR_BODY;
1162 } else {
1163 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1164 if (dstbody == NULL) {
1165 return false;
1168 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1169 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1172 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1173 * pointing to
1174 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1175 * then duplicate this. Else use talloc_memdup().
1178 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1179 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1180 } else if (srcdyn == NULL) {
1181 dstdyn = NULL;
1182 } else {
1183 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1184 if (dstdyn == NULL) {
1185 return false;
1188 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1189 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1191 return true;
1194 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1196 struct smbd_smb2_request *newreq = NULL;
1197 struct iovec *outvec = NULL;
1198 int count = req->out.vector_count;
1199 int i;
1200 bool ok;
1202 newreq = smbd_smb2_request_allocate(req->xconn);
1203 if (!newreq) {
1204 return NULL;
1207 newreq->sconn = req->sconn;
1208 newreq->xconn = req->xconn;
1209 newreq->session = req->session;
1210 newreq->do_encryption = req->do_encryption;
1211 newreq->do_signing = req->do_signing;
1212 newreq->current_idx = req->current_idx;
1214 outvec = talloc_zero_array(newreq, struct iovec, count);
1215 if (!outvec) {
1216 TALLOC_FREE(newreq);
1217 return NULL;
1219 newreq->out.vector = outvec;
1220 newreq->out.vector_count = count;
1222 /* Setup the outvec's identically to req. */
1223 outvec[0].iov_base = newreq->out.nbt_hdr;
1224 outvec[0].iov_len = 4;
1225 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1227 /* Setup the vectors identically to the ones in req. */
1228 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1229 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1230 break;
1234 if (i < count) {
1235 /* Alloc failed. */
1236 TALLOC_FREE(newreq);
1237 return NULL;
1240 ok = smb2_setup_nbt_length(newreq->out.vector,
1241 newreq->out.vector_count);
1242 if (!ok) {
1243 TALLOC_FREE(newreq);
1244 return NULL;
1247 return newreq;
1250 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1252 struct smbXsrv_connection *xconn = req->xconn;
1253 int first_idx = 1;
1254 struct iovec *firsttf = NULL;
1255 struct iovec *outhdr_v = NULL;
1256 uint8_t *outhdr = NULL;
1257 struct smbd_smb2_request *nreq = NULL;
1258 NTSTATUS status;
1259 bool ok;
1261 /* Create a new smb2 request we'll use
1262 for the interim return. */
1263 nreq = dup_smb2_req(req);
1264 if (!nreq) {
1265 return NT_STATUS_NO_MEMORY;
1268 /* Lose the last X out vectors. They're the
1269 ones we'll be using for the async reply. */
1270 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1272 ok = smb2_setup_nbt_length(nreq->out.vector,
1273 nreq->out.vector_count);
1274 if (!ok) {
1275 return NT_STATUS_INVALID_PARAMETER_MIX;
1278 /* Step back to the previous reply. */
1279 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1280 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1281 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1282 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1283 /* And end the chain. */
1284 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1286 /* Calculate outgoing credits */
1287 smb2_calculate_credits(req, nreq);
1289 if (DEBUGLEVEL >= 10) {
1290 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1291 (unsigned int)nreq->current_idx );
1292 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1293 (unsigned int)nreq->out.vector_count );
1294 print_req_vectors(nreq);
1298 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1299 * we need to sign/encrypt here with the last/first key we remembered
1301 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1302 status = smb2_signing_encrypt_pdu(req->first_key,
1303 xconn->smb2.server.cipher,
1304 firsttf,
1305 nreq->out.vector_count - first_idx);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 return status;
1309 } else if (req->last_key.length > 0) {
1310 status = smb2_signing_sign_pdu(req->last_key,
1311 xconn->protocol,
1312 outhdr_v,
1313 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 return status;
1319 nreq->queue_entry.mem_ctx = nreq;
1320 nreq->queue_entry.vector = nreq->out.vector;
1321 nreq->queue_entry.count = nreq->out.vector_count;
1322 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1323 xconn->smb2.send_queue_len++;
1325 status = smbd_smb2_flush_send_queue(xconn);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 return status;
1330 return NT_STATUS_OK;
1333 struct smbd_smb2_request_pending_state {
1334 struct smbd_smb2_send_queue queue_entry;
1335 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1336 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1339 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1340 struct tevent_timer *te,
1341 struct timeval current_time,
1342 void *private_data);
1344 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1345 struct tevent_req *subreq,
1346 uint32_t defer_time)
1348 NTSTATUS status;
1349 struct timeval defer_endtime;
1350 uint8_t *outhdr = NULL;
1351 uint32_t flags;
1353 if (!tevent_req_is_in_progress(subreq)) {
1355 * This is a performance optimization,
1356 * it avoids one tevent_loop iteration,
1357 * which means we avoid one
1358 * talloc_stackframe_pool/talloc_free pair.
1360 tevent_req_notify_callback(subreq);
1361 return NT_STATUS_OK;
1364 req->subreq = subreq;
1365 subreq = NULL;
1367 if (req->async_te) {
1368 /* We're already async. */
1369 return NT_STATUS_OK;
1372 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1373 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1374 if (flags & SMB2_HDR_FLAG_ASYNC) {
1375 /* We're already async. */
1376 return NT_STATUS_OK;
1379 if (req->async_internal) {
1381 * An SMB2 request implementation wants to handle the request
1382 * asynchronously "internally" while keeping synchronous
1383 * behaviour for the SMB2 request. This means we don't send an
1384 * interim response and we can allow processing of compound SMB2
1385 * requests (cf the subsequent check) for all cases.
1387 return NT_STATUS_OK;
1390 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1392 * We're trying to go async in a compound request
1393 * chain. This is only allowed for opens that cause an
1394 * oplock break or for the last operation in the
1395 * chain, otherwise it is not allowed. See
1396 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1398 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1400 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1402 * Cancel the outstanding request.
1404 bool ok = tevent_req_cancel(req->subreq);
1405 if (ok) {
1406 return NT_STATUS_OK;
1408 TALLOC_FREE(req->subreq);
1409 return smbd_smb2_request_error(req,
1410 NT_STATUS_INTERNAL_ERROR);
1414 if (DEBUGLEVEL >= 10) {
1415 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1416 (unsigned int)req->current_idx );
1417 print_req_vectors(req);
1420 if (req->current_idx > 1) {
1422 * We're going async in a compound
1423 * chain after the first request has
1424 * already been processed. Send an
1425 * interim response containing the
1426 * set of replies already generated.
1428 int idx = req->current_idx;
1430 status = smb2_send_async_interim_response(req);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 return status;
1434 if (req->first_key.length > 0) {
1435 data_blob_clear_free(&req->first_key);
1438 req->current_idx = 1;
1441 * Re-arrange the in.vectors to remove what
1442 * we just sent.
1444 memmove(&req->in.vector[1],
1445 &req->in.vector[idx],
1446 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1447 req->in.vector_count = 1 + (req->in.vector_count - idx);
1449 /* Re-arrange the out.vectors to match. */
1450 memmove(&req->out.vector[1],
1451 &req->out.vector[idx],
1452 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1453 req->out.vector_count = 1 + (req->out.vector_count - idx);
1455 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1457 * We only have one remaining request as
1458 * we've processed everything else.
1459 * This is no longer a compound request.
1461 req->compound_related = false;
1462 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1463 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1464 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1467 if (req->last_key.length > 0) {
1468 data_blob_clear_free(&req->last_key);
1471 defer_endtime = timeval_current_ofs_usec(defer_time);
1472 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1473 req, defer_endtime,
1474 smbd_smb2_request_pending_timer,
1475 req);
1476 if (req->async_te == NULL) {
1477 return NT_STATUS_NO_MEMORY;
1480 return NT_STATUS_OK;
1483 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1484 struct smbXsrv_connection *xconn)
1486 struct smbXsrv_channel_global0 *c = NULL;
1487 NTSTATUS status;
1488 DATA_BLOB key = data_blob_null;
1490 status = smbXsrv_session_find_channel(session, xconn, &c);
1491 if (NT_STATUS_IS_OK(status)) {
1492 key = c->signing_key;
1495 if (key.length == 0) {
1496 key = session->global->signing_key;
1499 return key;
1502 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1503 uint64_t *new_nonce_high,
1504 uint64_t *new_nonce_low)
1506 uint64_t nonce_high;
1507 uint64_t nonce_low;
1509 session->nonce_low += 1;
1510 if (session->nonce_low == 0) {
1511 session->nonce_low += 1;
1512 session->nonce_high += 1;
1516 * CCM and GCM algorithms must never have their
1517 * nonce wrap, or the security of the whole
1518 * communication and the keys is destroyed.
1519 * We must drop the connection once we have
1520 * transfered too much data.
1522 * NOTE: We assume nonces greater than 8 bytes.
1524 if (session->nonce_high >= session->nonce_high_max) {
1525 return NT_STATUS_ENCRYPTION_FAILED;
1528 nonce_high = session->nonce_high_random;
1529 nonce_high += session->nonce_high;
1530 nonce_low = session->nonce_low;
1532 *new_nonce_high = nonce_high;
1533 *new_nonce_low = nonce_low;
1534 return NT_STATUS_OK;
1537 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1538 struct tevent_timer *te,
1539 struct timeval current_time,
1540 void *private_data)
1542 struct smbd_smb2_request *req =
1543 talloc_get_type_abort(private_data,
1544 struct smbd_smb2_request);
1545 struct smbXsrv_connection *xconn = req->xconn;
1546 struct smbd_smb2_request_pending_state *state = NULL;
1547 uint8_t *outhdr = NULL;
1548 const uint8_t *inhdr = NULL;
1549 uint8_t *tf = NULL;
1550 size_t tf_len = 0;
1551 uint8_t *hdr = NULL;
1552 uint8_t *body = NULL;
1553 uint8_t *dyn = NULL;
1554 uint32_t flags = 0;
1555 uint64_t session_id = 0;
1556 uint64_t message_id = 0;
1557 uint64_t nonce_high = 0;
1558 uint64_t nonce_low = 0;
1559 uint64_t async_id = 0;
1560 NTSTATUS status;
1561 bool ok;
1563 TALLOC_FREE(req->async_te);
1565 /* Ensure our final reply matches the interim one. */
1566 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1567 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1568 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1569 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1570 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1572 async_id = message_id; /* keep it simple for now... */
1574 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1575 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1577 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1578 "going async\n",
1579 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1580 (unsigned long long)async_id ));
1583 * What we send is identical to a smbd_smb2_request_error
1584 * packet with an error status of STATUS_PENDING. Make use
1585 * of this fact sometime when refactoring. JRA.
1588 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1589 if (state == NULL) {
1590 smbd_server_connection_terminate(xconn,
1591 nt_errstr(NT_STATUS_NO_MEMORY));
1592 return;
1595 tf = state->buf + NBT_HDR_SIZE;
1596 tf_len = SMB2_TF_HDR_SIZE;
1598 hdr = tf + SMB2_TF_HDR_SIZE;
1599 body = hdr + SMB2_HDR_BODY;
1600 dyn = body + 8;
1602 if (req->do_encryption) {
1603 status = smb2_get_new_nonce(req->session,
1604 &nonce_high,
1605 &nonce_low);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 smbd_server_connection_terminate(xconn,
1608 nt_errstr(status));
1609 return;
1613 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1614 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1615 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1616 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1618 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1619 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1620 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1621 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1622 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1624 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1625 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1626 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1627 SBVAL(hdr, SMB2_HDR_PID, async_id);
1628 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1629 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1630 memcpy(hdr+SMB2_HDR_SIGNATURE,
1631 outhdr+SMB2_HDR_SIGNATURE, 16);
1633 SSVAL(body, 0x00, 0x08 + 1);
1635 SCVAL(body, 0x02, 0);
1636 SCVAL(body, 0x03, 0);
1637 SIVAL(body, 0x04, 0);
1638 /* Match W2K8R2... */
1639 SCVAL(dyn, 0x00, 0x21);
1641 state->vector[0].iov_base = (void *)state->buf;
1642 state->vector[0].iov_len = NBT_HDR_SIZE;
1644 if (req->do_encryption) {
1645 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1646 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1647 } else {
1648 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1649 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1652 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1653 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1655 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1656 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1658 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1659 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1661 ok = smb2_setup_nbt_length(state->vector,
1662 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1663 if (!ok) {
1664 smbd_server_connection_terminate(
1665 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1666 return;
1669 /* Ensure we correctly go through crediting. Grant
1670 the credits now, and zero credits on the final
1671 response. */
1672 smb2_set_operation_credit(req->xconn,
1673 SMBD_SMB2_IN_HDR_IOV(req),
1674 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1676 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1678 if (DEBUGLVL(10)) {
1679 int i;
1681 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1682 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1683 (unsigned int)i,
1684 (unsigned int)ARRAY_SIZE(state->vector),
1685 (unsigned int)state->vector[i].iov_len);
1689 if (req->do_encryption) {
1690 struct smbXsrv_session *x = req->session;
1691 DATA_BLOB encryption_key = x->global->encryption_key;
1693 status = smb2_signing_encrypt_pdu(encryption_key,
1694 xconn->smb2.server.cipher,
1695 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1696 SMBD_SMB2_NUM_IOV_PER_REQ);
1697 if (!NT_STATUS_IS_OK(status)) {
1698 smbd_server_connection_terminate(xconn,
1699 nt_errstr(status));
1700 return;
1702 } else if (req->do_signing) {
1703 struct smbXsrv_session *x = req->session;
1704 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1706 status = smb2_signing_sign_pdu(signing_key,
1707 xconn->protocol,
1708 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1709 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 smbd_server_connection_terminate(xconn,
1712 nt_errstr(status));
1713 return;
1717 state->queue_entry.mem_ctx = state;
1718 state->queue_entry.vector = state->vector;
1719 state->queue_entry.count = ARRAY_SIZE(state->vector);
1720 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
1721 xconn->smb2.send_queue_len++;
1723 status = smbd_smb2_flush_send_queue(xconn);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 smbd_server_connection_terminate(xconn,
1726 nt_errstr(status));
1727 return;
1731 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1733 struct smbXsrv_connection *xconn = req->xconn;
1734 struct smbd_smb2_request *cur;
1735 const uint8_t *inhdr;
1736 uint32_t flags;
1737 uint64_t search_message_id;
1738 uint64_t search_async_id;
1739 uint64_t found_id;
1741 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1743 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1744 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1745 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1748 * We don't need the request anymore cancel requests never
1749 * have a response.
1751 * We defer the TALLOC_FREE(req) to the caller.
1753 DLIST_REMOVE(xconn->smb2.requests, req);
1755 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1756 const uint8_t *outhdr;
1757 uint64_t message_id;
1758 uint64_t async_id;
1760 if (cur->compound_related) {
1762 * Never cancel anything in a compound request.
1763 * Way too hard to deal with the result.
1765 continue;
1768 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1770 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1771 async_id = BVAL(outhdr, SMB2_HDR_PID);
1773 if (flags & SMB2_HDR_FLAG_ASYNC) {
1774 if (search_async_id == async_id) {
1775 found_id = async_id;
1776 break;
1778 } else {
1779 if (search_message_id == message_id) {
1780 found_id = message_id;
1781 break;
1786 if (cur && cur->subreq) {
1787 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1788 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1789 "cancel opcode[%s] mid %llu\n",
1790 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1791 (unsigned long long)found_id ));
1792 tevent_req_cancel(cur->subreq);
1795 return NT_STATUS_OK;
1798 /*************************************************************
1799 Ensure an incoming tid is a valid one for us to access.
1800 Change to the associated uid credentials and chdir to the
1801 valid tid directory.
1802 *************************************************************/
1804 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1806 const uint8_t *inhdr;
1807 uint32_t in_flags;
1808 uint32_t in_tid;
1809 struct smbXsrv_tcon *tcon;
1810 NTSTATUS status;
1811 NTTIME now = timeval_to_nttime(&req->request_time);
1813 req->tcon = NULL;
1815 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1817 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1818 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1820 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1821 in_tid = req->last_tid;
1824 req->last_tid = 0;
1826 status = smb2srv_tcon_lookup(req->session,
1827 in_tid, now, &tcon);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 return status;
1832 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1833 return NT_STATUS_ACCESS_DENIED;
1836 if (!set_current_service(tcon->compat, 0, true)) {
1837 return NT_STATUS_ACCESS_DENIED;
1840 req->tcon = tcon;
1841 req->last_tid = in_tid;
1843 return NT_STATUS_OK;
1846 /*************************************************************
1847 Ensure an incoming session_id is a valid one for us to access.
1848 *************************************************************/
1850 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1852 const uint8_t *inhdr;
1853 uint32_t in_flags;
1854 uint16_t in_opcode;
1855 uint64_t in_session_id;
1856 struct smbXsrv_session *session = NULL;
1857 struct auth_session_info *session_info;
1858 NTSTATUS status;
1859 NTTIME now = timeval_to_nttime(&req->request_time);
1861 req->session = NULL;
1862 req->tcon = NULL;
1864 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1866 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1867 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1868 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1870 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1871 in_session_id = req->last_session_id;
1874 req->last_session_id = 0;
1876 /* look an existing session up */
1877 switch (in_opcode) {
1878 case SMB2_OP_SESSSETUP:
1880 * For a session bind request, we don't have the
1881 * channel set up at this point yet, so we defer
1882 * the verification that the connection belongs
1883 * to the session to the session setup code, which
1884 * can look at the session binding flags.
1886 status = smb2srv_session_lookup_client(req->xconn->client,
1887 in_session_id, now,
1888 &session);
1889 break;
1890 default:
1891 status = smb2srv_session_lookup_conn(req->xconn,
1892 in_session_id, now,
1893 &session);
1894 break;
1896 if (session) {
1897 req->session = session;
1898 req->last_session_id = in_session_id;
1900 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1901 switch (in_opcode) {
1902 case SMB2_OP_SESSSETUP:
1903 status = NT_STATUS_OK;
1904 break;
1905 case SMB2_OP_LOGOFF:
1906 case SMB2_OP_CLOSE:
1907 case SMB2_OP_LOCK:
1908 case SMB2_OP_CANCEL:
1909 case SMB2_OP_KEEPALIVE:
1911 * [MS-SMB2] 3.3.5.2.9 Verifying the Session
1912 * specifies that LOGOFF, CLOSE and (UN)LOCK
1913 * should always be processed even on expired sessions.
1915 * Also see the logic in
1916 * smbd_smb2_request_process_lock().
1918 * The smb2.session.expire2 test shows that
1919 * CANCEL and KEEPALIVE/ECHO should also
1920 * be processed.
1922 status = NT_STATUS_OK;
1923 break;
1924 default:
1925 break;
1928 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1929 switch (in_opcode) {
1930 case SMB2_OP_TCON:
1931 case SMB2_OP_CREATE:
1932 case SMB2_OP_GETINFO:
1933 case SMB2_OP_SETINFO:
1934 return NT_STATUS_INVALID_HANDLE;
1935 default:
1937 * Notice the check for
1938 * (session_info == NULL)
1939 * below.
1941 status = NT_STATUS_OK;
1942 break;
1945 if (!NT_STATUS_IS_OK(status)) {
1946 return status;
1949 session_info = session->global->auth_session_info;
1950 if (session_info == NULL) {
1951 return NT_STATUS_INVALID_HANDLE;
1954 if (in_session_id != req->xconn->client->last_session_id) {
1955 req->xconn->client->last_session_id = in_session_id;
1956 set_current_user_info(session_info->unix_info->sanitized_username,
1957 session_info->unix_info->unix_name,
1958 session_info->info->domain_name);
1961 return NT_STATUS_OK;
1964 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1965 uint32_t data_length)
1967 struct smbXsrv_connection *xconn = req->xconn;
1968 uint16_t needed_charge;
1969 uint16_t credit_charge = 1;
1970 const uint8_t *inhdr;
1972 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1974 if (xconn->smb2.credits.multicredit) {
1975 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1976 credit_charge = MAX(credit_charge, 1);
1979 needed_charge = (data_length - 1)/ 65536 + 1;
1981 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1982 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1983 credit_charge, needed_charge));
1985 if (needed_charge > credit_charge) {
1986 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1987 credit_charge, needed_charge));
1988 return NT_STATUS_INVALID_PARAMETER;
1991 return NT_STATUS_OK;
1994 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1995 size_t expected_body_size)
1997 struct iovec *inhdr_v;
1998 const uint8_t *inhdr;
1999 uint16_t opcode;
2000 const uint8_t *inbody;
2001 size_t body_size;
2002 size_t min_dyn_size = expected_body_size & 0x00000001;
2003 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2006 * The following should be checked already.
2008 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2009 return NT_STATUS_INTERNAL_ERROR;
2011 if (req->current_idx > max_idx) {
2012 return NT_STATUS_INTERNAL_ERROR;
2015 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2016 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2017 return NT_STATUS_INTERNAL_ERROR;
2019 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2020 return NT_STATUS_INTERNAL_ERROR;
2023 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2024 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2026 switch (opcode) {
2027 case SMB2_OP_IOCTL:
2028 case SMB2_OP_GETINFO:
2029 min_dyn_size = 0;
2030 break;
2031 case SMB2_OP_WRITE:
2032 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
2033 if (req->smb1req->unread_bytes < min_dyn_size) {
2034 return NT_STATUS_INVALID_PARAMETER;
2037 min_dyn_size = 0;
2039 break;
2043 * Now check the expected body size,
2044 * where the last byte might be in the
2045 * dynamic section..
2047 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2048 return NT_STATUS_INVALID_PARAMETER;
2050 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2051 return NT_STATUS_INVALID_PARAMETER;
2054 inbody = SMBD_SMB2_IN_BODY_PTR(req);
2056 body_size = SVAL(inbody, 0x00);
2057 if (body_size != expected_body_size) {
2058 return NT_STATUS_INVALID_PARAMETER;
2061 return NT_STATUS_OK;
2064 bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2066 return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2068 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2069 SMBXSRV_ENCRYPTION_DESIRED |
2070 SMBXSRV_ENCRYPTION_REQUIRED)));
2073 bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2075 return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2076 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2079 /* Set a flag if not already set, return true if set */
2080 bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2082 if ((flag == 0) || (*flags & flag)) {
2083 return false;
2086 *flags |= flag;
2087 return true;
2091 * Update encryption state tracking flags, this can be used to
2092 * determine whether whether the session or tcon is "encrypted".
2094 static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2095 uint16_t opcode,
2096 bool *update_session_globalp,
2097 bool *update_tcon_globalp)
2099 /* Default: assume unecrypted and unsigned */
2100 struct smbXsrv_session *session = req->session;
2101 struct smbXsrv_tcon *tcon = req->tcon;
2102 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2103 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2104 bool update_session = false;
2105 bool update_tcon = false;
2107 if (req->was_encrypted && req->do_encryption) {
2108 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2109 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2110 } else {
2111 /* Unencrypted packet, can be signed */
2112 if (req->do_signing) {
2113 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2114 } else if (opcode == SMB2_OP_CANCEL) {
2115 /* Cancel requests are allowed to skip signing */
2116 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2120 update_session |= smbXsrv_set_crypto_flag(
2121 &session->global->encryption_flags, encrypt_flag);
2122 update_session |= smbXsrv_set_crypto_flag(
2123 &session->global->signing_flags, sign_flag);
2125 if (tcon) {
2126 update_tcon |= smbXsrv_set_crypto_flag(
2127 &tcon->global->encryption_flags, encrypt_flag);
2128 update_tcon |= smbXsrv_set_crypto_flag(
2129 &tcon->global->signing_flags, sign_flag);
2132 *update_session_globalp = update_session;
2133 *update_tcon_globalp = update_tcon;
2134 return;
2137 bool smbXsrv_is_signed(uint8_t signing_flags)
2140 * Signing is always enabled, so unless we got an unsigned
2141 * packet and at least one signed packet that was not
2142 * encrypted, the session or tcon is "signed".
2144 return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2145 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2148 bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2150 return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2151 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2154 static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2155 struct smbd_smb2_request *req,
2156 bool modify_call)
2158 struct smbXsrv_connection *xconn = req->xconn;
2159 const uint8_t *inhdr;
2160 uint16_t channel_sequence;
2161 uint32_t flags;
2162 int cmp;
2163 struct smbXsrv_open *op;
2164 bool update_open = false;
2165 NTSTATUS status = NT_STATUS_OK;
2167 req->request_counters_updated = false;
2169 if (xconn->protocol < PROTOCOL_SMB2_22) {
2170 return NT_STATUS_OK;
2173 if (req->compat_chain_fsp == NULL) {
2174 return NT_STATUS_OK;
2177 op = req->compat_chain_fsp->op;
2178 if (op == NULL) {
2179 return NT_STATUS_OK;
2182 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2183 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2184 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2186 cmp = channel_sequence - op->global->channel_sequence;
2188 if (abs(cmp) > INT16_MAX) {
2190 * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2192 * If the channel sequence number of the request and the one
2193 * known to the server are not equal, the channel sequence
2194 * number and outstanding request counts are only updated
2195 * "... if the unsigned difference using 16-bit arithmetic
2196 * between ChannelSequence and Open.ChannelSequence is less than
2197 * or equal to 0x7FFF ...".
2198 * Otherwise, an error is returned for the modifying
2199 * calls write, set_info, and ioctl.
2201 * There are currently two issues with the description:
2203 * * For the other calls, the document seems to imply
2204 * that processing continues without adapting the
2205 * counters (if the sequence numbers are not equal).
2207 * TODO: This needs clarification!
2209 * * Also, the behaviour if the difference is larger
2210 * than 0x7FFF is not clear. The document seems to
2211 * imply that if such a difference is reached,
2212 * the server starts to ignore the counters or
2213 * in the case of the modifying calls, return errors.
2215 * TODO: This needs clarification!
2217 * At this point Samba tries to be a little more
2218 * clever than the description in the MS-SMB2 document
2219 * by heuristically detecting and properly treating
2220 * a 16 bit overflow of the client-submitted sequence
2221 * number:
2223 * If the stored channel sequence number is more than
2224 * 0x7FFF larger than the one from the request, then
2225 * the client-provided sequence number has likely
2226 * overflown. We treat this case as valid instead
2227 * of as failure.
2229 * The MS-SMB2 behaviour would be setting cmp = -1.
2231 cmp *= -1;
2234 if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) {
2235 if (cmp == 0) {
2236 op->request_count += 1;
2237 req->request_counters_updated = true;
2238 } else if (cmp > 0) {
2239 op->pre_request_count += op->request_count;
2240 op->request_count = 1;
2241 op->global->channel_sequence = channel_sequence;
2242 update_open = true;
2243 req->request_counters_updated = true;
2244 } else if (modify_call) {
2245 return NT_STATUS_FILE_NOT_AVAILABLE;
2247 } else {
2248 if (cmp == 0 && op->pre_request_count == 0) {
2249 op->request_count += 1;
2250 req->request_counters_updated = true;
2251 } else if (cmp > 0 && op->pre_request_count == 0) {
2252 op->pre_request_count += op->request_count;
2253 op->request_count = 1;
2254 op->global->channel_sequence = channel_sequence;
2255 update_open = true;
2256 req->request_counters_updated = true;
2257 } else if (modify_call) {
2258 return NT_STATUS_FILE_NOT_AVAILABLE;
2262 if (update_open) {
2263 status = smbXsrv_open_update(op);
2266 return status;
2269 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2271 struct smbXsrv_connection *xconn = req->xconn;
2272 const struct smbd_smb2_dispatch_table *call = NULL;
2273 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2274 const uint8_t *inhdr;
2275 uint16_t opcode;
2276 uint32_t flags;
2277 uint64_t mid;
2278 NTSTATUS status;
2279 NTSTATUS session_status;
2280 uint32_t allowed_flags;
2281 NTSTATUS return_value;
2282 struct smbXsrv_session *x = NULL;
2283 bool signing_required = false;
2284 bool encryption_desired = false;
2285 bool encryption_required = false;
2287 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2289 DO_PROFILE_INC(request);
2291 /* TODO: verify more things */
2293 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2294 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2295 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2296 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2297 smb2_opcode_name(opcode),
2298 (unsigned long long)mid));
2300 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2302 * once the protocol is negotiated
2303 * SMB2_OP_NEGPROT is not allowed anymore
2305 if (opcode == SMB2_OP_NEGPROT) {
2306 /* drop the connection */
2307 return NT_STATUS_INVALID_PARAMETER;
2309 } else {
2311 * if the protocol is not negotiated yet
2312 * only SMB2_OP_NEGPROT is allowed.
2314 if (opcode != SMB2_OP_NEGPROT) {
2315 /* drop the connection */
2316 return NT_STATUS_INVALID_PARAMETER;
2321 * Check if the client provided a valid session id,
2322 * if so smbd_smb2_request_check_session() calls
2323 * set_current_user_info().
2325 * As some command don't require a valid session id
2326 * we defer the check of the session_status
2328 session_status = smbd_smb2_request_check_session(req);
2329 x = req->session;
2330 if (x != NULL) {
2331 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
2332 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2333 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2336 req->async_internal = false;
2337 req->do_signing = false;
2338 req->do_encryption = false;
2339 req->was_encrypted = false;
2340 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2341 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2342 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2344 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2345 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2346 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2347 (unsigned long long)x->global->session_wire_id,
2348 (unsigned long long)tf_session_id));
2350 * TODO: windows allows this...
2351 * should we drop the connection?
2353 * For now we just return ACCESS_DENIED
2354 * (Windows clients never trigger this)
2355 * and wait for an update of [MS-SMB2].
2357 return smbd_smb2_request_error(req,
2358 NT_STATUS_ACCESS_DENIED);
2361 req->was_encrypted = true;
2364 if (encryption_required && !req->was_encrypted) {
2365 return smbd_smb2_request_error(req,
2366 NT_STATUS_ACCESS_DENIED);
2369 call = smbd_smb2_call(opcode);
2370 if (call == NULL) {
2371 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2374 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2375 SMB2_HDR_FLAG_SIGNED |
2376 SMB2_HDR_FLAG_DFS;
2377 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2378 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2380 if (opcode == SMB2_OP_NEGPROT) {
2381 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2382 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2385 if (opcode == SMB2_OP_CANCEL) {
2386 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2388 if (xconn->protocol >= PROTOCOL_SMB2_22) {
2389 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
2391 if ((flags & ~allowed_flags) != 0) {
2392 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2395 if (flags & SMB2_HDR_FLAG_CHAINED) {
2397 * This check is mostly for giving the correct error code
2398 * for compounded requests.
2400 if (!NT_STATUS_IS_OK(session_status)) {
2401 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2403 } else {
2404 req->compat_chain_fsp = NULL;
2407 if (req->was_encrypted) {
2408 signing_required = false;
2409 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2410 DATA_BLOB signing_key = data_blob_null;
2412 if (x == NULL) {
2414 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2415 * If the SMB2 header of the SMB2 NEGOTIATE
2416 * request has the SMB2_FLAGS_SIGNED bit set in the
2417 * Flags field, the server MUST fail the request
2418 * with STATUS_INVALID_PARAMETER.
2420 * Microsoft test tool checks this.
2423 if ((opcode == SMB2_OP_NEGPROT) &&
2424 (flags & SMB2_HDR_FLAG_SIGNED)) {
2425 status = NT_STATUS_INVALID_PARAMETER;
2426 } else {
2427 status = NT_STATUS_USER_SESSION_DELETED;
2429 return smbd_smb2_request_error(req, status);
2432 signing_key = smbd_smb2_signing_key(x, xconn);
2435 * If we have a signing key, we should
2436 * sign the response
2438 if (signing_key.length > 0) {
2439 req->do_signing = true;
2442 status = smb2_signing_check_pdu(signing_key,
2443 xconn->protocol,
2444 SMBD_SMB2_IN_HDR_IOV(req),
2445 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2446 if (!NT_STATUS_IS_OK(status)) {
2447 return smbd_smb2_request_error(req, status);
2451 * Now that we know the request was correctly signed
2452 * we have to sign the response too.
2454 req->do_signing = true;
2456 if (!NT_STATUS_IS_OK(session_status)) {
2457 return smbd_smb2_request_error(req, session_status);
2459 } else if (opcode == SMB2_OP_CANCEL) {
2460 /* Cancel requests are allowed to skip the signing */
2461 } else if (signing_required) {
2463 * If signing is required we try to sign
2464 * a possible error response
2466 req->do_signing = true;
2467 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2470 if (flags & SMB2_HDR_FLAG_CHAINED) {
2471 req->compound_related = true;
2474 if (call->need_session) {
2475 if (!NT_STATUS_IS_OK(session_status)) {
2476 return smbd_smb2_request_error(req, session_status);
2480 if (call->need_tcon) {
2481 SMB_ASSERT(call->need_session);
2484 * This call needs to be run as user.
2486 * smbd_smb2_request_check_tcon()
2487 * calls change_to_user() on success.
2489 status = smbd_smb2_request_check_tcon(req);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 return smbd_smb2_request_error(req, status);
2493 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2494 encryption_desired = true;
2496 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2497 encryption_required = true;
2499 if (encryption_required && !req->was_encrypted) {
2500 return smbd_smb2_request_error(req,
2501 NT_STATUS_ACCESS_DENIED);
2505 if (req->was_encrypted || encryption_desired) {
2506 req->do_encryption = true;
2509 if (req->session) {
2510 bool update_session_global = false;
2511 bool update_tcon_global = false;
2513 smb2srv_update_crypto_flags(req, opcode,
2514 &update_session_global,
2515 &update_tcon_global);
2517 if (update_session_global) {
2518 status = smbXsrv_session_update(x);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 return smbd_smb2_request_error(req, status);
2523 if (update_tcon_global) {
2524 status = smbXsrv_tcon_update(req->tcon);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 return smbd_smb2_request_error(req, status);
2531 if (call->fileid_ofs != 0) {
2532 size_t needed = call->fileid_ofs + 16;
2533 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2534 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2535 uint64_t file_id_persistent;
2536 uint64_t file_id_volatile;
2537 struct files_struct *fsp;
2539 SMB_ASSERT(call->need_tcon);
2541 if (needed > body_size) {
2542 return smbd_smb2_request_error(req,
2543 NT_STATUS_INVALID_PARAMETER);
2546 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2547 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2549 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2550 if (fsp == NULL) {
2551 if (!call->allow_invalid_fileid) {
2552 return smbd_smb2_request_error(req,
2553 NT_STATUS_FILE_CLOSED);
2556 if (file_id_persistent != UINT64_MAX) {
2557 return smbd_smb2_request_error(req,
2558 NT_STATUS_FILE_CLOSED);
2560 if (file_id_volatile != UINT64_MAX) {
2561 return smbd_smb2_request_error(req,
2562 NT_STATUS_FILE_CLOSED);
2567 status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 return smbd_smb2_request_error(req, status);
2572 if (call->as_root) {
2573 SMB_ASSERT(call->fileid_ofs == 0);
2574 /* This call needs to be run as root */
2575 change_to_root_user();
2576 } else {
2577 SMB_ASSERT(call->need_tcon);
2580 #define _INBYTES(_r) \
2581 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2583 switch (opcode) {
2584 case SMB2_OP_NEGPROT:
2585 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2586 req->profile, _INBYTES(req));
2587 return_value = smbd_smb2_request_process_negprot(req);
2588 break;
2590 case SMB2_OP_SESSSETUP:
2591 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2592 req->profile, _INBYTES(req));
2593 return_value = smbd_smb2_request_process_sesssetup(req);
2594 break;
2596 case SMB2_OP_LOGOFF:
2597 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2598 req->profile, _INBYTES(req));
2599 return_value = smbd_smb2_request_process_logoff(req);
2600 break;
2602 case SMB2_OP_TCON:
2603 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2604 req->profile, _INBYTES(req));
2605 return_value = smbd_smb2_request_process_tcon(req);
2606 break;
2608 case SMB2_OP_TDIS:
2609 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2610 req->profile, _INBYTES(req));
2611 return_value = smbd_smb2_request_process_tdis(req);
2612 break;
2614 case SMB2_OP_CREATE:
2615 if (req->subreq == NULL) {
2616 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2617 req->profile, _INBYTES(req));
2618 } else {
2619 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2621 return_value = smbd_smb2_request_process_create(req);
2622 break;
2624 case SMB2_OP_CLOSE:
2625 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2626 req->profile, _INBYTES(req));
2627 return_value = smbd_smb2_request_process_close(req);
2628 break;
2630 case SMB2_OP_FLUSH:
2631 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2632 req->profile, _INBYTES(req));
2633 return_value = smbd_smb2_request_process_flush(req);
2634 break;
2636 case SMB2_OP_READ:
2637 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2638 req->profile, _INBYTES(req));
2639 return_value = smbd_smb2_request_process_read(req);
2640 break;
2642 case SMB2_OP_WRITE:
2643 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2644 req->profile, _INBYTES(req));
2645 return_value = smbd_smb2_request_process_write(req);
2646 break;
2648 case SMB2_OP_LOCK:
2649 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2650 req->profile, _INBYTES(req));
2651 return_value = smbd_smb2_request_process_lock(req);
2652 break;
2654 case SMB2_OP_IOCTL:
2655 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2656 req->profile, _INBYTES(req));
2657 return_value = smbd_smb2_request_process_ioctl(req);
2658 break;
2660 case SMB2_OP_CANCEL:
2661 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2662 req->profile, _INBYTES(req));
2663 return_value = smbd_smb2_request_process_cancel(req);
2664 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2667 * We don't need the request anymore cancel requests never
2668 * have a response.
2670 * smbd_smb2_request_process_cancel() already called
2671 * DLIST_REMOVE(xconn->smb2.requests, req);
2673 TALLOC_FREE(req);
2675 break;
2677 case SMB2_OP_KEEPALIVE:
2678 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2679 req->profile, _INBYTES(req));
2680 return_value = smbd_smb2_request_process_keepalive(req);
2681 break;
2683 case SMB2_OP_QUERY_DIRECTORY:
2684 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2685 req->profile, _INBYTES(req));
2686 return_value = smbd_smb2_request_process_query_directory(req);
2687 break;
2689 case SMB2_OP_NOTIFY:
2690 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2691 req->profile, _INBYTES(req));
2692 return_value = smbd_smb2_request_process_notify(req);
2693 break;
2695 case SMB2_OP_GETINFO:
2696 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2697 req->profile, _INBYTES(req));
2698 return_value = smbd_smb2_request_process_getinfo(req);
2699 break;
2701 case SMB2_OP_SETINFO:
2702 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2703 req->profile, _INBYTES(req));
2704 return_value = smbd_smb2_request_process_setinfo(req);
2705 break;
2707 case SMB2_OP_BREAK:
2708 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2709 req->profile, _INBYTES(req));
2710 return_value = smbd_smb2_request_process_break(req);
2711 break;
2713 default:
2714 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2715 break;
2717 return return_value;
2720 static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
2722 struct smbXsrv_connection *xconn = req->xconn;
2723 const uint8_t *inhdr;
2724 uint16_t channel_sequence;
2725 struct smbXsrv_open *op;
2727 if (!req->request_counters_updated) {
2728 return;
2731 if (xconn->protocol < PROTOCOL_SMB2_22) {
2732 return;
2735 if (req->compat_chain_fsp == NULL) {
2736 return;
2739 op = req->compat_chain_fsp->op;
2740 if (op == NULL) {
2741 return;
2744 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2745 channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2747 if (op->global->channel_sequence == channel_sequence) {
2748 SMB_ASSERT(op->request_count > 0);
2749 op->request_count -= 1;
2750 } else {
2751 SMB_ASSERT(op->pre_request_count > 0);
2752 op->pre_request_count -= 1;
2756 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2758 struct smbXsrv_connection *xconn = req->xconn;
2759 int first_idx = 1;
2760 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2761 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2762 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2763 NTSTATUS status;
2764 bool ok;
2766 req->subreq = NULL;
2767 TALLOC_FREE(req->async_te);
2769 /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
2770 smbd_smb2_request_reply_update_counts(req);
2772 if (req->do_encryption &&
2773 (firsttf->iov_len == 0) &&
2774 (req->first_key.length == 0) &&
2775 (req->session != NULL) &&
2776 (req->session->global->encryption_key.length != 0))
2778 DATA_BLOB encryption_key = req->session->global->encryption_key;
2779 uint8_t *tf;
2780 uint64_t session_id = req->session->global->session_wire_id;
2781 uint64_t nonce_high;
2782 uint64_t nonce_low;
2784 status = smb2_get_new_nonce(req->session,
2785 &nonce_high,
2786 &nonce_low);
2787 if (!NT_STATUS_IS_OK(status)) {
2788 return status;
2792 * We need to place the SMB2_TRANSFORM header before the
2793 * first SMB2 header
2797 * we need to remember the encryption key
2798 * and defer the signing/encryption until
2799 * we are sure that we do not change
2800 * the header again.
2802 req->first_key = data_blob_dup_talloc(req, encryption_key);
2803 if (req->first_key.data == NULL) {
2804 return NT_STATUS_NO_MEMORY;
2807 tf = talloc_zero_array(req, uint8_t,
2808 SMB2_TF_HDR_SIZE);
2809 if (tf == NULL) {
2810 return NT_STATUS_NO_MEMORY;
2813 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2814 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2815 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2816 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2818 firsttf->iov_base = (void *)tf;
2819 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2822 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2823 (req->last_key.length > 0) &&
2824 (firsttf->iov_len == 0))
2826 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2827 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2830 * As we are sure the header of the last request in the
2831 * compound chain will not change, we can to sign here
2832 * with the last signing key we remembered.
2834 status = smb2_signing_sign_pdu(req->last_key,
2835 xconn->protocol,
2836 lasthdr,
2837 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2838 if (!NT_STATUS_IS_OK(status)) {
2839 return status;
2842 if (req->last_key.length > 0) {
2843 data_blob_clear_free(&req->last_key);
2846 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2847 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2849 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2851 if (req->current_idx < req->out.vector_count) {
2853 * We must process the remaining compound
2854 * SMB2 requests before any new incoming SMB2
2855 * requests. This is because incoming SMB2
2856 * requests may include a cancel for a
2857 * compound request we haven't processed
2858 * yet.
2860 struct tevent_immediate *im = tevent_create_immediate(req);
2861 if (!im) {
2862 return NT_STATUS_NO_MEMORY;
2865 if (req->do_signing && firsttf->iov_len == 0) {
2866 struct smbXsrv_session *x = req->session;
2867 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2870 * we need to remember the signing key
2871 * and defer the signing until
2872 * we are sure that we do not change
2873 * the header again.
2875 req->last_key = data_blob_dup_talloc(req, signing_key);
2876 if (req->last_key.data == NULL) {
2877 return NT_STATUS_NO_MEMORY;
2881 tevent_schedule_immediate(im,
2882 req->sconn->ev_ctx,
2883 smbd_smb2_request_dispatch_immediate,
2884 req);
2885 return NT_STATUS_OK;
2888 if (req->compound_related) {
2889 req->compound_related = false;
2892 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2893 if (!ok) {
2894 return NT_STATUS_INVALID_PARAMETER_MIX;
2897 /* Set credit for these operations (zero credits if this
2898 is a final reply for an async operation). */
2899 smb2_calculate_credits(req, req);
2902 * now check if we need to sign the current response
2904 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2905 status = smb2_signing_encrypt_pdu(req->first_key,
2906 xconn->smb2.server.cipher,
2907 firsttf,
2908 req->out.vector_count - first_idx);
2909 if (!NT_STATUS_IS_OK(status)) {
2910 return status;
2912 } else if (req->do_signing) {
2913 struct smbXsrv_session *x = req->session;
2914 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2916 status = smb2_signing_sign_pdu(signing_key,
2917 xconn->protocol,
2918 outhdr,
2919 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2920 if (!NT_STATUS_IS_OK(status)) {
2921 return status;
2924 if (req->first_key.length > 0) {
2925 data_blob_clear_free(&req->first_key);
2928 if (req->preauth != NULL) {
2929 struct hc_sha512state sctx;
2930 int i;
2932 samba_SHA512_Init(&sctx);
2933 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2934 sizeof(req->preauth->sha512_value));
2935 for (i = 1; i < req->in.vector_count; i++) {
2936 samba_SHA512_Update(&sctx,
2937 req->in.vector[i].iov_base,
2938 req->in.vector[i].iov_len);
2940 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2942 samba_SHA512_Init(&sctx);
2943 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2944 sizeof(req->preauth->sha512_value));
2945 for (i = 1; i < req->out.vector_count; i++) {
2946 samba_SHA512_Update(&sctx,
2947 req->out.vector[i].iov_base,
2948 req->out.vector[i].iov_len);
2950 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2952 req->preauth = NULL;
2955 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2956 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2957 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2958 /* Dynamic part is NULL. Chop it off,
2959 We're going to send it via sendfile. */
2960 req->out.vector_count -= 1;
2964 * We're done with this request -
2965 * move it off the "being processed" queue.
2967 DLIST_REMOVE(xconn->smb2.requests, req);
2969 req->queue_entry.mem_ctx = req;
2970 req->queue_entry.vector = req->out.vector;
2971 req->queue_entry.count = req->out.vector_count;
2972 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
2973 xconn->smb2.send_queue_len++;
2975 status = smbd_smb2_flush_send_queue(xconn);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 return status;
2980 return NT_STATUS_OK;
2983 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2985 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2986 struct tevent_immediate *im,
2987 void *private_data)
2989 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2990 struct smbd_smb2_request);
2991 struct smbXsrv_connection *xconn = req->xconn;
2992 NTSTATUS status;
2994 TALLOC_FREE(im);
2996 if (DEBUGLEVEL >= 10) {
2997 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2998 req->current_idx, req->in.vector_count));
2999 print_req_vectors(req);
3002 status = smbd_smb2_request_dispatch(req);
3003 if (!NT_STATUS_IS_OK(status)) {
3004 smbd_server_connection_terminate(xconn, nt_errstr(status));
3005 return;
3008 status = smbd_smb2_request_next_incoming(xconn);
3009 if (!NT_STATUS_IS_OK(status)) {
3010 smbd_server_connection_terminate(xconn, nt_errstr(status));
3011 return;
3015 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3016 NTSTATUS status,
3017 DATA_BLOB body, DATA_BLOB *dyn,
3018 const char *location)
3020 uint8_t *outhdr;
3021 struct iovec *outbody_v;
3022 struct iovec *outdyn_v;
3023 uint32_t next_command_ofs;
3025 DEBUG(10,("smbd_smb2_request_done_ex: "
3026 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
3027 req->current_idx, nt_errstr(status), (unsigned int)body.length,
3028 dyn ? "yes": "no",
3029 (unsigned int)(dyn ? dyn->length : 0),
3030 location));
3032 if (body.length < 2) {
3033 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3036 if ((body.length % 2) != 0) {
3037 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3040 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3041 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3042 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3044 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3045 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3047 outbody_v->iov_base = (void *)body.data;
3048 outbody_v->iov_len = body.length;
3050 if (dyn) {
3051 outdyn_v->iov_base = (void *)dyn->data;
3052 outdyn_v->iov_len = dyn->length;
3053 } else {
3054 outdyn_v->iov_base = NULL;
3055 outdyn_v->iov_len = 0;
3059 * See if we need to recalculate the offset to the next response
3061 * Note that all responses may require padding (including the very last
3062 * one).
3064 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3065 next_command_ofs = SMB2_HDR_BODY;
3066 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3067 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3070 if ((next_command_ofs % 8) != 0) {
3071 size_t pad_size = 8 - (next_command_ofs % 8);
3072 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3074 * if the dyn buffer is empty
3075 * we can use it to add padding
3077 uint8_t *pad;
3079 pad = talloc_zero_array(req,
3080 uint8_t, pad_size);
3081 if (pad == NULL) {
3082 return smbd_smb2_request_error(req,
3083 NT_STATUS_NO_MEMORY);
3086 outdyn_v->iov_base = (void *)pad;
3087 outdyn_v->iov_len = pad_size;
3088 } else {
3090 * For now we copy the dynamic buffer
3091 * and add the padding to the new buffer
3093 size_t old_size;
3094 uint8_t *old_dyn;
3095 size_t new_size;
3096 uint8_t *new_dyn;
3098 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3099 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3101 new_size = old_size + pad_size;
3102 new_dyn = talloc_zero_array(req,
3103 uint8_t, new_size);
3104 if (new_dyn == NULL) {
3105 return smbd_smb2_request_error(req,
3106 NT_STATUS_NO_MEMORY);
3109 memcpy(new_dyn, old_dyn, old_size);
3110 memset(new_dyn + old_size, 0, pad_size);
3112 outdyn_v->iov_base = (void *)new_dyn;
3113 outdyn_v->iov_len = new_size;
3115 next_command_ofs += pad_size;
3118 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3119 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3120 } else {
3121 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3123 return smbd_smb2_request_reply(req);
3126 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3127 NTSTATUS status,
3128 DATA_BLOB *info,
3129 const char *location)
3131 struct smbXsrv_connection *xconn = req->xconn;
3132 DATA_BLOB body;
3133 DATA_BLOB _dyn;
3134 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3135 size_t unread_bytes = smbd_smb2_unread_bytes(req);
3137 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3138 "at %s\n", req->current_idx, nt_errstr(status),
3139 info ? " +info" : "", location);
3141 if (unread_bytes) {
3142 /* Recvfile error. Drain incoming socket. */
3143 size_t ret;
3145 errno = 0;
3146 ret = drain_socket(xconn->transport.sock, unread_bytes);
3147 if (ret != unread_bytes) {
3148 NTSTATUS error;
3150 if (errno == 0) {
3151 error = NT_STATUS_IO_DEVICE_ERROR;
3152 } else {
3153 error = map_nt_error_from_unix_common(errno);
3156 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3157 "ret[%u] errno[%d] => %s\n",
3158 (unsigned)unread_bytes,
3159 (unsigned)ret, errno, nt_errstr(error)));
3160 return error;
3164 body.data = outhdr + SMB2_HDR_BODY;
3165 body.length = 8;
3166 SSVAL(body.data, 0, 9);
3168 if (info) {
3169 SIVAL(body.data, 0x04, info->length);
3170 } else {
3171 /* Allocated size of req->out.vector[i].iov_base
3172 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3173 * 1 byte without having to do an alloc.
3175 info = &_dyn;
3176 info->data = ((uint8_t *)outhdr) +
3177 OUTVEC_ALLOC_SIZE - 1;
3178 info->length = 1;
3179 SCVAL(info->data, 0, 0);
3183 * Note: Even if there is an error, continue to process the request.
3184 * per MS-SMB2.
3187 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
3191 struct smbd_smb2_send_break_state {
3192 struct smbd_smb2_send_queue queue_entry;
3193 uint8_t nbt_hdr[NBT_HDR_SIZE];
3194 uint8_t tf[SMB2_TF_HDR_SIZE];
3195 uint8_t hdr[SMB2_HDR_BODY];
3196 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
3197 uint8_t body[1];
3200 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
3201 struct smbXsrv_session *session,
3202 struct smbXsrv_tcon *tcon,
3203 const uint8_t *body,
3204 size_t body_len)
3206 struct smbd_smb2_send_break_state *state;
3207 bool do_encryption = false;
3208 uint64_t session_wire_id = 0;
3209 uint64_t nonce_high = 0;
3210 uint64_t nonce_low = 0;
3211 NTSTATUS status;
3212 size_t statelen;
3213 bool ok;
3215 if (session != NULL) {
3216 session_wire_id = session->global->session_wire_id;
3217 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3218 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3219 do_encryption = true;
3223 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
3224 body_len;
3226 state = talloc_zero_size(xconn, statelen);
3227 if (state == NULL) {
3228 return NT_STATUS_NO_MEMORY;
3230 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
3232 if (do_encryption) {
3233 status = smb2_get_new_nonce(session,
3234 &nonce_high,
3235 &nonce_low);
3236 if (!NT_STATUS_IS_OK(status)) {
3237 return status;
3241 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3242 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
3243 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
3244 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
3246 SIVAL(state->hdr, 0, SMB2_MAGIC);
3247 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
3248 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
3249 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
3250 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
3251 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
3252 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
3253 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
3254 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
3255 SIVAL(state->hdr, SMB2_HDR_PID, 0);
3256 SIVAL(state->hdr, SMB2_HDR_TID, 0);
3257 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
3258 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
3260 state->vector[0] = (struct iovec) {
3261 .iov_base = state->nbt_hdr,
3262 .iov_len = sizeof(state->nbt_hdr)
3265 if (do_encryption) {
3266 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3267 .iov_base = state->tf,
3268 .iov_len = sizeof(state->tf)
3270 } else {
3271 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
3272 .iov_base = NULL,
3273 .iov_len = 0
3277 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
3278 .iov_base = state->hdr,
3279 .iov_len = sizeof(state->hdr)
3282 memcpy(state->body, body, body_len);
3284 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
3285 .iov_base = state->body,
3286 .iov_len = body_len /* no sizeof(state->body) .. :-) */
3290 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
3293 ok = smb2_setup_nbt_length(state->vector,
3294 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
3295 if (!ok) {
3296 return NT_STATUS_INVALID_PARAMETER_MIX;
3299 if (do_encryption) {
3300 DATA_BLOB encryption_key = session->global->encryption_key;
3302 status = smb2_signing_encrypt_pdu(encryption_key,
3303 xconn->smb2.server.cipher,
3304 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
3305 SMBD_SMB2_NUM_IOV_PER_REQ);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 return status;
3311 state->queue_entry.mem_ctx = state;
3312 state->queue_entry.vector = state->vector;
3313 state->queue_entry.count = ARRAY_SIZE(state->vector);
3314 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
3315 xconn->smb2.send_queue_len++;
3317 status = smbd_smb2_flush_send_queue(xconn);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 return status;
3322 return NT_STATUS_OK;
3325 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
3326 struct smbXsrv_session *session,
3327 struct smbXsrv_tcon *tcon,
3328 struct smbXsrv_open *op,
3329 uint8_t oplock_level)
3331 uint8_t body[0x18];
3333 SSVAL(body, 0x00, sizeof(body));
3334 SCVAL(body, 0x02, oplock_level);
3335 SCVAL(body, 0x03, 0); /* reserved */
3336 SIVAL(body, 0x04, 0); /* reserved */
3337 SBVAL(body, 0x08, op->global->open_persistent_id);
3338 SBVAL(body, 0x10, op->global->open_volatile_id);
3340 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3343 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3344 uint16_t new_epoch,
3345 uint32_t lease_flags,
3346 struct smb2_lease_key *lease_key,
3347 uint32_t current_lease_state,
3348 uint32_t new_lease_state)
3350 uint8_t body[0x2c];
3352 SSVAL(body, 0x00, sizeof(body));
3353 SSVAL(body, 0x02, new_epoch);
3354 SIVAL(body, 0x04, lease_flags);
3355 SBVAL(body, 0x08, lease_key->data[0]);
3356 SBVAL(body, 0x10, lease_key->data[1]);
3357 SIVAL(body, 0x18, current_lease_state);
3358 SIVAL(body, 0x1c, new_lease_state);
3359 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3360 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3361 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3363 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3366 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3368 NTSTATUS status;
3369 uint32_t flags;
3370 uint64_t file_id_persistent;
3371 uint64_t file_id_volatile;
3372 struct smbXsrv_open *op = NULL;
3373 struct files_struct *fsp = NULL;
3374 const uint8_t *body = NULL;
3377 * This is only called with a pktbuf
3378 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3379 * bytes
3382 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3383 /* Transform header. Cannot recvfile. */
3384 return false;
3386 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3387 /* Not SMB2. Normal error path will cope. */
3388 return false;
3390 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3391 /* Not SMB2. Normal error path will cope. */
3392 return false;
3394 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3395 /* Needs to be a WRITE. */
3396 return false;
3398 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3399 /* Chained. Cannot recvfile. */
3400 return false;
3402 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3403 if (flags & SMB2_HDR_FLAG_CHAINED) {
3404 /* Chained. Cannot recvfile. */
3405 return false;
3407 if (flags & SMB2_HDR_FLAG_SIGNED) {
3408 /* Signed. Cannot recvfile. */
3409 return false;
3412 body = &state->pktbuf[SMB2_HDR_BODY];
3414 file_id_persistent = BVAL(body, 0x10);
3415 file_id_volatile = BVAL(body, 0x18);
3417 status = smb2srv_open_lookup(state->req->xconn,
3418 file_id_persistent,
3419 file_id_volatile,
3420 0, /* now */
3421 &op);
3422 if (!NT_STATUS_IS_OK(status)) {
3423 return false;
3426 fsp = op->compat;
3427 if (fsp == NULL) {
3428 return false;
3430 if (fsp->conn == NULL) {
3431 return false;
3434 if (IS_IPC(fsp->conn)) {
3435 return false;
3437 if (IS_PRINT(fsp->conn)) {
3438 return false;
3441 DEBUG(10,("Doing recvfile write len = %u\n",
3442 (unsigned int)(state->pktfull - state->pktlen)));
3444 return true;
3447 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3449 struct smbd_server_connection *sconn = xconn->client->sconn;
3450 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3451 size_t max_send_queue_len;
3452 size_t cur_send_queue_len;
3454 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3456 * we're not supposed to do any io
3458 return NT_STATUS_OK;
3461 if (state->req != NULL) {
3463 * if there is already a tstream_readv_pdu
3464 * pending, we are done.
3466 return NT_STATUS_OK;
3469 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3470 cur_send_queue_len = xconn->smb2.send_queue_len;
3472 if (cur_send_queue_len > max_send_queue_len) {
3474 * if we have a lot of requests to send,
3475 * we wait until they are on the wire until we
3476 * ask for the next request.
3478 return NT_STATUS_OK;
3481 /* ask for the next request */
3482 ZERO_STRUCTP(state);
3483 state->req = smbd_smb2_request_allocate(xconn);
3484 if (state->req == NULL) {
3485 return NT_STATUS_NO_MEMORY;
3487 state->req->sconn = sconn;
3488 state->req->xconn = xconn;
3489 state->min_recv_size = lp_min_receive_file_size();
3491 TEVENT_FD_READABLE(xconn->transport.fde);
3493 return NT_STATUS_OK;
3496 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3497 uint64_t expected_seq_low,
3498 const uint8_t *inpdu, size_t size)
3500 struct smbd_server_connection *sconn = xconn->client->sconn;
3501 NTSTATUS status;
3502 struct smbd_smb2_request *req = NULL;
3504 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3505 (unsigned int)size));
3507 status = smbd_initialize_smb2(xconn, expected_seq_low);
3508 if (!NT_STATUS_IS_OK(status)) {
3509 smbd_server_connection_terminate(xconn, nt_errstr(status));
3510 return;
3513 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3514 if (!NT_STATUS_IS_OK(status)) {
3515 smbd_server_connection_terminate(xconn, nt_errstr(status));
3516 return;
3519 status = smbd_smb2_request_validate(req);
3520 if (!NT_STATUS_IS_OK(status)) {
3521 smbd_server_connection_terminate(xconn, nt_errstr(status));
3522 return;
3525 status = smbd_smb2_request_setup_out(req);
3526 if (!NT_STATUS_IS_OK(status)) {
3527 smbd_server_connection_terminate(xconn, nt_errstr(status));
3528 return;
3531 #ifdef WITH_PROFILE
3533 * this was already counted at the SMB1 layer =>
3534 * smbd_smb2_request_dispatch() should not count it twice.
3536 if (profile_p->values.request_stats.count > 0) {
3537 profile_p->values.request_stats.count--;
3539 #endif
3540 status = smbd_smb2_request_dispatch(req);
3541 if (!NT_STATUS_IS_OK(status)) {
3542 smbd_server_connection_terminate(xconn, nt_errstr(status));
3543 return;
3546 status = smbd_smb2_request_next_incoming(xconn);
3547 if (!NT_STATUS_IS_OK(status)) {
3548 smbd_server_connection_terminate(xconn, nt_errstr(status));
3549 return;
3552 sconn->num_requests++;
3555 static int socket_error_from_errno(int ret,
3556 int sys_errno,
3557 bool *retry)
3559 *retry = false;
3561 if (ret >= 0) {
3562 return 0;
3565 if (ret != -1) {
3566 return EIO;
3569 if (sys_errno == 0) {
3570 return EIO;
3573 if (sys_errno == EINTR) {
3574 *retry = true;
3575 return sys_errno;
3578 if (sys_errno == EINPROGRESS) {
3579 *retry = true;
3580 return sys_errno;
3583 if (sys_errno == EAGAIN) {
3584 *retry = true;
3585 return sys_errno;
3588 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3589 if (sys_errno == ENOMEM) {
3590 *retry = true;
3591 return sys_errno;
3594 #ifdef EWOULDBLOCK
3595 #if EWOULDBLOCK != EAGAIN
3596 if (sys_errno == EWOULDBLOCK) {
3597 *retry = true;
3598 return sys_errno;
3600 #endif
3601 #endif
3603 return sys_errno;
3606 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3608 int ret;
3609 int err;
3610 bool retry;
3611 NTSTATUS status;
3613 if (xconn->smb2.send_queue == NULL) {
3614 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3615 return NT_STATUS_OK;
3618 while (xconn->smb2.send_queue != NULL) {
3619 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3620 bool ok;
3622 if (e->sendfile_header != NULL) {
3623 size_t size = 0;
3624 size_t i = 0;
3625 uint8_t *buf;
3627 status = NT_STATUS_INTERNAL_ERROR;
3629 for (i=0; i < e->count; i++) {
3630 size += e->vector[i].iov_len;
3633 if (size <= e->sendfile_header->length) {
3634 buf = e->sendfile_header->data;
3635 } else {
3636 buf = talloc_array(e->mem_ctx, uint8_t, size);
3637 if (buf == NULL) {
3638 return NT_STATUS_NO_MEMORY;
3642 size = 0;
3643 for (i=0; i < e->count; i++) {
3644 memcpy(buf+size,
3645 e->vector[i].iov_base,
3646 e->vector[i].iov_len);
3647 size += e->vector[i].iov_len;
3650 e->sendfile_header->data = buf;
3651 e->sendfile_header->length = size;
3652 e->sendfile_status = &status;
3653 e->count = 0;
3655 xconn->smb2.send_queue_len--;
3656 DLIST_REMOVE(xconn->smb2.send_queue, e);
3658 * This triggers the sendfile path via
3659 * the destructor.
3661 talloc_free(e->mem_ctx);
3663 if (!NT_STATUS_IS_OK(status)) {
3664 return status;
3666 continue;
3669 ret = writev(xconn->transport.sock, e->vector, e->count);
3670 if (ret == 0) {
3671 /* propagate end of file */
3672 return NT_STATUS_INTERNAL_ERROR;
3674 err = socket_error_from_errno(ret, errno, &retry);
3675 if (retry) {
3676 /* retry later */
3677 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3678 return NT_STATUS_OK;
3680 if (err != 0) {
3681 return map_nt_error_from_unix_common(err);
3684 ok = iov_advance(&e->vector, &e->count, ret);
3685 if (!ok) {
3686 return NT_STATUS_INTERNAL_ERROR;
3689 if (e->count > 0) {
3690 /* we have more to write */
3691 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3692 return NT_STATUS_OK;
3695 xconn->smb2.send_queue_len--;
3696 DLIST_REMOVE(xconn->smb2.send_queue, e);
3697 talloc_free(e->mem_ctx);
3701 * Restart reads if we were blocked on
3702 * draining the send queue.
3705 status = smbd_smb2_request_next_incoming(xconn);
3706 if (!NT_STATUS_IS_OK(status)) {
3707 return status;
3710 return NT_STATUS_OK;
3713 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3714 uint16_t fde_flags)
3716 struct smbd_server_connection *sconn = xconn->client->sconn;
3717 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3718 struct smbd_smb2_request *req = NULL;
3719 size_t min_recvfile_size = UINT32_MAX;
3720 int ret;
3721 int err;
3722 bool retry;
3723 NTSTATUS status;
3724 NTTIME now;
3726 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3728 * we're not supposed to do any io
3730 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3731 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3732 return NT_STATUS_OK;
3735 if (fde_flags & TEVENT_FD_WRITE) {
3736 status = smbd_smb2_flush_send_queue(xconn);
3737 if (!NT_STATUS_IS_OK(status)) {
3738 return status;
3742 if (!(fde_flags & TEVENT_FD_READ)) {
3743 return NT_STATUS_OK;
3746 if (state->req == NULL) {
3747 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3748 return NT_STATUS_OK;
3751 again:
3752 if (!state->hdr.done) {
3753 state->hdr.done = true;
3755 state->vector.iov_base = (void *)state->hdr.nbt;
3756 state->vector.iov_len = NBT_HDR_SIZE;
3759 ret = readv(xconn->transport.sock, &state->vector, 1);
3760 if (ret == 0) {
3761 /* propagate end of file */
3762 return NT_STATUS_END_OF_FILE;
3764 err = socket_error_from_errno(ret, errno, &retry);
3765 if (retry) {
3766 /* retry later */
3767 TEVENT_FD_READABLE(xconn->transport.fde);
3768 return NT_STATUS_OK;
3770 if (err != 0) {
3771 return map_nt_error_from_unix_common(err);
3774 if (ret < state->vector.iov_len) {
3775 uint8_t *base;
3776 base = (uint8_t *)state->vector.iov_base;
3777 base += ret;
3778 state->vector.iov_base = (void *)base;
3779 state->vector.iov_len -= ret;
3780 /* we have more to read */
3781 TEVENT_FD_READABLE(xconn->transport.fde);
3782 return NT_STATUS_OK;
3785 if (state->pktlen > 0) {
3786 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3788 * Not a possible receivefile write.
3789 * Read the rest of the data.
3791 state->doing_receivefile = false;
3793 state->pktbuf = talloc_realloc(state->req,
3794 state->pktbuf,
3795 uint8_t,
3796 state->pktfull);
3797 if (state->pktbuf == NULL) {
3798 return NT_STATUS_NO_MEMORY;
3801 state->vector.iov_base = (void *)(state->pktbuf +
3802 state->pktlen);
3803 state->vector.iov_len = (state->pktfull -
3804 state->pktlen);
3806 state->pktlen = state->pktfull;
3807 goto again;
3811 * Either this is a receivefile write so we've
3812 * done a short read, or if not we have all the data.
3814 goto got_full;
3818 * Now we analyze the NBT header
3820 if (state->hdr.nbt[0] != 0x00) {
3821 state->min_recv_size = 0;
3823 state->pktfull = smb2_len(state->hdr.nbt);
3824 if (state->pktfull == 0) {
3825 goto got_full;
3828 if (state->min_recv_size != 0) {
3829 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3830 min_recvfile_size += state->min_recv_size;
3833 if (state->pktfull > min_recvfile_size) {
3835 * Might be a receivefile write. Read the SMB2 HEADER +
3836 * SMB2_WRITE header first. Set 'doing_receivefile'
3837 * as we're *attempting* receivefile write. If this
3838 * turns out not to be a SMB2_WRITE request or otherwise
3839 * not suitable then we'll just read the rest of the data
3840 * the next time this function is called.
3842 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3843 state->doing_receivefile = true;
3844 } else {
3845 state->pktlen = state->pktfull;
3848 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3849 if (state->pktbuf == NULL) {
3850 return NT_STATUS_NO_MEMORY;
3853 state->vector.iov_base = (void *)state->pktbuf;
3854 state->vector.iov_len = state->pktlen;
3856 goto again;
3858 got_full:
3860 if (state->hdr.nbt[0] != 0x00) {
3861 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3862 state->hdr.nbt[0]));
3864 req = state->req;
3865 ZERO_STRUCTP(state);
3866 state->req = req;
3867 state->min_recv_size = lp_min_receive_file_size();
3868 req = NULL;
3869 goto again;
3872 req = state->req;
3873 state->req = NULL;
3875 req->request_time = timeval_current();
3876 now = timeval_to_nttime(&req->request_time);
3878 status = smbd_smb2_inbuf_parse_compound(xconn,
3879 now,
3880 state->pktbuf,
3881 state->pktlen,
3882 req,
3883 &req->in.vector,
3884 &req->in.vector_count);
3885 if (!NT_STATUS_IS_OK(status)) {
3886 return status;
3889 if (state->doing_receivefile) {
3890 req->smb1req = talloc_zero(req, struct smb_request);
3891 if (req->smb1req == NULL) {
3892 return NT_STATUS_NO_MEMORY;
3894 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3897 ZERO_STRUCTP(state);
3899 req->current_idx = 1;
3901 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3902 req->current_idx, req->in.vector_count));
3904 status = smbd_smb2_request_validate(req);
3905 if (!NT_STATUS_IS_OK(status)) {
3906 return status;
3909 status = smbd_smb2_request_setup_out(req);
3910 if (!NT_STATUS_IS_OK(status)) {
3911 return status;
3914 status = smbd_smb2_request_dispatch(req);
3915 if (!NT_STATUS_IS_OK(status)) {
3916 return status;
3919 sconn->num_requests++;
3921 /* The timeout_processing function isn't run nearly
3922 often enough to implement 'max log size' without
3923 overrunning the size of the file by many megabytes.
3924 This is especially true if we are running at debug
3925 level 10. Checking every 50 SMB2s is a nice
3926 tradeoff of performance vs log file size overrun. */
3928 if ((sconn->num_requests % 50) == 0 &&
3929 need_to_check_log_size()) {
3930 change_to_root_user();
3931 check_log_size();
3934 status = smbd_smb2_request_next_incoming(xconn);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 return status;
3939 return NT_STATUS_OK;
3942 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3943 struct tevent_fd *fde,
3944 uint16_t flags,
3945 void *private_data)
3947 struct smbXsrv_connection *xconn =
3948 talloc_get_type_abort(private_data,
3949 struct smbXsrv_connection);
3950 NTSTATUS status;
3952 status = smbd_smb2_io_handler(xconn, flags);
3953 if (!NT_STATUS_IS_OK(status)) {
3954 smbd_server_connection_terminate(xconn, nt_errstr(status));
3955 return;