s3:smb2_server: convert encryption desired and required bools to flags
[Samba.git] / source3 / smbd / smb2_server.c
blobbd8261a153f148f8dda397e8f69d3748b5129404
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 } smbd_smb2_table[] = {
50 #define _OP(o) .opcode = o, .name = #o
52 _OP(SMB2_OP_NEGPROT),
53 .as_root = true,
54 },{
55 _OP(SMB2_OP_SESSSETUP),
56 .as_root = true,
57 },{
58 _OP(SMB2_OP_LOGOFF),
59 .need_session = true,
60 .as_root = true,
61 },{
62 _OP(SMB2_OP_TCON),
63 .need_session = true,
65 * This call needs to be run as root.
67 * smbd_smb2_request_process_tcon()
68 * calls make_connection_snum(), which will call
69 * change_to_user(), when needed.
71 .as_root = true,
72 },{
73 _OP(SMB2_OP_TDIS),
74 .need_session = true,
75 .need_tcon = true,
76 .as_root = true,
77 },{
78 _OP(SMB2_OP_CREATE),
79 .need_session = true,
80 .need_tcon = true,
81 },{
82 _OP(SMB2_OP_CLOSE),
83 .need_session = true,
84 .need_tcon = true,
85 .fileid_ofs = 0x08,
86 },{
87 _OP(SMB2_OP_FLUSH),
88 .need_session = true,
89 .need_tcon = true,
90 .fileid_ofs = 0x08,
91 },{
92 _OP(SMB2_OP_READ),
93 .need_session = true,
94 .need_tcon = true,
95 .fileid_ofs = 0x10,
96 },{
97 _OP(SMB2_OP_WRITE),
98 .need_session = true,
99 .need_tcon = true,
100 .fileid_ofs = 0x10,
102 _OP(SMB2_OP_LOCK),
103 .need_session = true,
104 .need_tcon = true,
105 .fileid_ofs = 0x08,
107 _OP(SMB2_OP_IOCTL),
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
111 .allow_invalid_fileid = true,
113 _OP(SMB2_OP_CANCEL),
114 .as_root = true,
116 _OP(SMB2_OP_KEEPALIVE),
117 .as_root = true,
119 _OP(SMB2_OP_QUERY_DIRECTORY),
120 .need_session = true,
121 .need_tcon = true,
122 .fileid_ofs = 0x08,
124 _OP(SMB2_OP_NOTIFY),
125 .need_session = true,
126 .need_tcon = true,
127 .fileid_ofs = 0x08,
129 _OP(SMB2_OP_GETINFO),
130 .need_session = true,
131 .need_tcon = true,
132 .fileid_ofs = 0x18,
134 _OP(SMB2_OP_SETINFO),
135 .need_session = true,
136 .need_tcon = true,
137 .fileid_ofs = 0x10,
139 _OP(SMB2_OP_BREAK),
140 .need_session = true,
141 .need_tcon = true,
143 * we do not set
144 * .fileid_ofs here
145 * as LEASE breaks does not
146 * have a file id
151 const char *smb2_opcode_name(uint16_t opcode)
153 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
154 return "Bad SMB2 opcode";
156 return smbd_smb2_table[opcode].name;
159 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
161 const struct smbd_smb2_dispatch_table *ret = NULL;
163 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
164 return NULL;
167 ret = &smbd_smb2_table[opcode];
169 SMB_ASSERT(ret->opcode == opcode);
171 return ret;
174 static void print_req_vectors(const struct smbd_smb2_request *req)
176 int i;
178 for (i = 0; i < req->in.vector_count; i++) {
179 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
180 (unsigned int)i,
181 (unsigned int)req->in.vector[i].iov_len);
183 for (i = 0; i < req->out.vector_count; i++) {
184 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
185 (unsigned int)i,
186 (unsigned int)req->out.vector[i].iov_len);
190 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
192 if (size < (4 + SMB2_HDR_BODY)) {
193 return false;
196 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
197 return false;
200 return true;
203 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
204 uint64_t expected_seq_low)
206 TALLOC_FREE(xconn->transport.fde);
208 xconn->smb2.credits.seq_low = expected_seq_low;
209 xconn->smb2.credits.seq_range = 1;
210 xconn->smb2.credits.granted = 1;
211 xconn->smb2.credits.max = lp_smb2_max_credits();
212 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
213 xconn->smb2.credits.max);
214 if (xconn->smb2.credits.bitmap == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
219 xconn,
220 xconn->transport.sock,
221 TEVENT_FD_READ,
222 smbd_smb2_connection_handler,
223 xconn);
224 if (xconn->transport.fde == NULL) {
225 return NT_STATUS_NO_MEMORY;
228 /* Ensure child is set to non-blocking mode */
229 set_blocking(xconn->transport.sock, false);
230 return NT_STATUS_OK;
233 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
234 #define _smb2_setlen(_buf,len) do { \
235 uint8_t *buf = (uint8_t *)_buf; \
236 buf[0] = 0; \
237 buf[1] = ((len)&0xFF0000)>>16; \
238 buf[2] = ((len)&0xFF00)>>8; \
239 buf[3] = (len)&0xFF; \
240 } while (0)
242 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
244 ssize_t len;
246 if (count == 0) {
247 return false;
250 len = iov_buflen(vector+1, count-1);
252 if ((len == -1) || (len > 0xFFFFFF)) {
253 return false;
256 _smb2_setlen(vector[0].iov_base, len);
257 return true;
260 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
262 if (req->first_key.length > 0) {
263 data_blob_clear_free(&req->first_key);
265 if (req->last_key.length > 0) {
266 data_blob_clear_free(&req->last_key);
268 return 0;
271 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
273 TALLOC_CTX *mem_pool;
274 struct smbd_smb2_request *req;
276 #if 0
277 /* Enable this to find subtle valgrind errors. */
278 mem_pool = talloc_init("smbd_smb2_request_allocate");
279 #else
280 mem_pool = talloc_tos();
281 #endif
282 if (mem_pool == NULL) {
283 return NULL;
286 req = talloc_zero(mem_pool, struct smbd_smb2_request);
287 if (req == NULL) {
288 talloc_free(mem_pool);
289 return NULL;
291 talloc_reparent(mem_pool, mem_ctx, req);
292 #if 0
293 TALLOC_FREE(mem_pool);
294 #endif
296 req->last_session_id = UINT64_MAX;
297 req->last_tid = UINT32_MAX;
299 talloc_set_destructor(req, smbd_smb2_request_destructor);
301 return req;
304 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
305 NTTIME now,
306 uint8_t *buf,
307 size_t buflen,
308 struct smbd_smb2_request *req,
309 struct iovec **piov,
310 int *pnum_iov)
312 TALLOC_CTX *mem_ctx = req;
313 struct iovec *iov;
314 int num_iov = 1;
315 size_t taken = 0;
316 uint8_t *first_hdr = buf;
317 size_t verified_buflen = 0;
318 uint8_t *tf = NULL;
319 size_t tf_len = 0;
322 * Note: index '0' is reserved for the transport protocol
324 iov = req->in._vector;
326 while (taken < buflen) {
327 size_t len = buflen - taken;
328 uint8_t *hdr = first_hdr + taken;
329 struct iovec *cur;
330 size_t full_size;
331 size_t next_command_ofs;
332 uint16_t body_size;
333 uint8_t *body = NULL;
334 uint32_t dyn_size;
335 uint8_t *dyn = NULL;
336 struct iovec *iov_alloc = NULL;
338 if (iov != req->in._vector) {
339 iov_alloc = iov;
342 if (verified_buflen > taken) {
343 len = verified_buflen - taken;
344 } else {
345 tf = NULL;
346 tf_len = 0;
349 if (len < 4) {
350 DEBUG(10, ("%d bytes left, expected at least %d\n",
351 (int)len, 4));
352 goto inval;
354 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
355 struct smbXsrv_session *s = NULL;
356 uint64_t uid;
357 struct iovec tf_iov[2];
358 NTSTATUS status;
359 size_t enc_len;
361 if (xconn->protocol < PROTOCOL_SMB2_24) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but dialect[0x%04X] is used\n",
364 xconn->smb2.server.dialect));
365 goto inval;
368 if (xconn->smb2.server.cipher == 0) {
369 DEBUG(10, ("Got SMB2_TRANSFORM header, "
370 "but not negotiated "
371 "client[0x%08X] server[0x%08X]\n",
372 xconn->smb2.client.capabilities,
373 xconn->smb2.server.capabilities));
374 goto inval;
377 if (len < SMB2_TF_HDR_SIZE) {
378 DEBUG(1, ("%d bytes left, expected at least %d\n",
379 (int)len, SMB2_TF_HDR_SIZE));
380 goto inval;
382 tf = hdr;
383 tf_len = SMB2_TF_HDR_SIZE;
384 taken += tf_len;
386 hdr = first_hdr + taken;
387 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
388 uid = BVAL(tf, SMB2_TF_SESSION_ID);
390 if (len < SMB2_TF_HDR_SIZE + enc_len) {
391 DEBUG(1, ("%d bytes left, expected at least %d\n",
392 (int)len,
393 (int)(SMB2_TF_HDR_SIZE + enc_len)));
394 goto inval;
397 status = smb2srv_session_lookup_conn(xconn, uid, now,
398 &s);
399 if (s == NULL) {
400 DEBUG(1, ("invalid session[%llu] in "
401 "SMB2_TRANSFORM header\n",
402 (unsigned long long)uid));
403 TALLOC_FREE(iov_alloc);
404 return NT_STATUS_USER_SESSION_DELETED;
407 tf_iov[0].iov_base = (void *)tf;
408 tf_iov[0].iov_len = tf_len;
409 tf_iov[1].iov_base = (void *)hdr;
410 tf_iov[1].iov_len = enc_len;
412 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
413 xconn->smb2.server.cipher,
414 tf_iov, 2);
415 if (!NT_STATUS_IS_OK(status)) {
416 TALLOC_FREE(iov_alloc);
417 return status;
420 verified_buflen = taken + enc_len;
421 len = enc_len;
425 * We need the header plus the body length field
428 if (len < SMB2_HDR_BODY + 2) {
429 DEBUG(10, ("%d bytes left, expected at least %d\n",
430 (int)len, SMB2_HDR_BODY));
431 goto inval;
433 if (IVAL(hdr, 0) != SMB2_MAGIC) {
434 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
435 IVAL(hdr, 0)));
436 goto inval;
438 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
439 DEBUG(10, ("Got HDR len %d, expected %d\n",
440 SVAL(hdr, 4), SMB2_HDR_BODY));
441 goto inval;
444 full_size = len;
445 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
446 body_size = SVAL(hdr, SMB2_HDR_BODY);
448 if (next_command_ofs != 0) {
449 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
450 goto inval;
452 if (next_command_ofs > full_size) {
453 goto inval;
455 full_size = next_command_ofs;
457 if (body_size < 2) {
458 goto inval;
460 body_size &= 0xfffe;
462 if (body_size > (full_size - SMB2_HDR_BODY)) {
464 * let the caller handle the error
466 body_size = full_size - SMB2_HDR_BODY;
468 body = hdr + SMB2_HDR_BODY;
469 dyn = body + body_size;
470 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
472 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
473 struct iovec *iov_tmp = NULL;
475 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
476 struct iovec,
477 num_iov +
478 SMBD_SMB2_NUM_IOV_PER_REQ);
479 if (iov_tmp == NULL) {
480 TALLOC_FREE(iov_alloc);
481 return NT_STATUS_NO_MEMORY;
484 if (iov_alloc == NULL) {
485 memcpy(iov_tmp,
486 req->in._vector,
487 sizeof(req->in._vector));
490 iov = iov_tmp;
492 cur = &iov[num_iov];
493 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
495 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
496 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
497 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
498 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
499 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
500 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
501 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
502 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
504 taken += full_size;
507 *piov = iov;
508 *pnum_iov = num_iov;
509 return NT_STATUS_OK;
511 inval:
512 if (iov != req->in._vector) {
513 TALLOC_FREE(iov);
515 return NT_STATUS_INVALID_PARAMETER;
518 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
519 const uint8_t *_inpdu, size_t size,
520 struct smbd_smb2_request **_req)
522 struct smbd_server_connection *sconn = xconn->client->sconn;
523 struct smbd_smb2_request *req;
524 uint32_t protocol_version;
525 uint8_t *inpdu = NULL;
526 const uint8_t *inhdr = NULL;
527 uint16_t cmd;
528 uint32_t next_command_ofs;
529 NTSTATUS status;
530 NTTIME now;
532 if (size < (SMB2_HDR_BODY + 2)) {
533 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
534 return NT_STATUS_INVALID_PARAMETER;
537 inhdr = _inpdu;
539 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
540 if (protocol_version != SMB2_MAGIC) {
541 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
542 protocol_version));
543 return NT_STATUS_INVALID_PARAMETER;
546 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
547 if (cmd != SMB2_OP_NEGPROT) {
548 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
549 cmd));
550 return NT_STATUS_INVALID_PARAMETER;
553 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
554 if (next_command_ofs != 0) {
555 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
556 next_command_ofs));
557 return NT_STATUS_INVALID_PARAMETER;
560 req = smbd_smb2_request_allocate(xconn);
561 if (req == NULL) {
562 return NT_STATUS_NO_MEMORY;
564 req->sconn = sconn;
565 req->xconn = xconn;
567 inpdu = talloc_memdup(req, _inpdu, size);
568 if (inpdu == NULL) {
569 return NT_STATUS_NO_MEMORY;
572 req->request_time = timeval_current();
573 now = timeval_to_nttime(&req->request_time);
575 status = smbd_smb2_inbuf_parse_compound(xconn,
576 now,
577 inpdu,
578 size,
579 req, &req->in.vector,
580 &req->in.vector_count);
581 if (!NT_STATUS_IS_OK(status)) {
582 TALLOC_FREE(req);
583 return status;
586 req->current_idx = 1;
588 *_req = req;
589 return NT_STATUS_OK;
592 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
593 uint64_t message_id, uint64_t seq_id)
595 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
596 unsigned int offset;
597 uint64_t seq_tmp;
599 seq_tmp = xconn->smb2.credits.seq_low;
600 if (seq_id < seq_tmp) {
601 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
602 "%llu (sequence id %llu) "
603 "(granted = %u, low = %llu, range = %u)\n",
604 (unsigned long long)message_id,
605 (unsigned long long)seq_id,
606 (unsigned int)xconn->smb2.credits.granted,
607 (unsigned long long)xconn->smb2.credits.seq_low,
608 (unsigned int)xconn->smb2.credits.seq_range));
609 return false;
612 seq_tmp += xconn->smb2.credits.seq_range;
613 if (seq_id >= seq_tmp) {
614 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
615 "%llu (sequence id %llu) "
616 "(granted = %u, low = %llu, range = %u)\n",
617 (unsigned long long)message_id,
618 (unsigned long long)seq_id,
619 (unsigned int)xconn->smb2.credits.granted,
620 (unsigned long long)xconn->smb2.credits.seq_low,
621 (unsigned int)xconn->smb2.credits.seq_range));
622 return false;
625 offset = seq_id % xconn->smb2.credits.max;
627 if (bitmap_query(credits_bm, offset)) {
628 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
629 "%llu (sequence id %llu) "
630 "(granted = %u, low = %llu, range = %u) "
631 "(bm offset %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 offset));
638 return false;
641 /* Mark the message_ids as seen in the bitmap. */
642 bitmap_set(credits_bm, offset);
644 if (seq_id != xconn->smb2.credits.seq_low) {
645 return true;
649 * Move the window forward by all the message_id's
650 * already seen.
652 while (bitmap_query(credits_bm, offset)) {
653 DEBUG(10,("smb2_validate_sequence_number: clearing "
654 "id %llu (position %u) from bitmap\n",
655 (unsigned long long)(xconn->smb2.credits.seq_low),
656 offset));
657 bitmap_clear(credits_bm, offset);
659 xconn->smb2.credits.seq_low += 1;
660 xconn->smb2.credits.seq_range -= 1;
661 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
664 return true;
667 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
668 const uint8_t *inhdr)
670 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
671 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
672 uint16_t credit_charge = 1;
673 uint64_t i;
675 if (opcode == SMB2_OP_CANCEL) {
676 /* SMB2_CANCEL requests by definition resend messageids. */
677 return true;
680 if (xconn->smb2.credits.multicredit) {
681 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
682 credit_charge = MAX(credit_charge, 1);
685 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
686 "credits_granted %llu, "
687 "seqnum low/range: %llu/%llu\n",
688 (unsigned long long) message_id,
689 (unsigned long long) credit_charge,
690 (unsigned long long) xconn->smb2.credits.granted,
691 (unsigned long long) xconn->smb2.credits.seq_low,
692 (unsigned long long) xconn->smb2.credits.seq_range));
694 if (xconn->smb2.credits.granted < credit_charge) {
695 DEBUG(0, ("smb2_validate_message_id: client used more "
696 "credits than granted, mid %llu, charge %llu, "
697 "credits_granted %llu, "
698 "seqnum low/range: %llu/%llu\n",
699 (unsigned long long) message_id,
700 (unsigned long long) credit_charge,
701 (unsigned long long) xconn->smb2.credits.granted,
702 (unsigned long long) xconn->smb2.credits.seq_low,
703 (unsigned long long) xconn->smb2.credits.seq_range));
704 return false;
708 * now check the message ids
710 * for multi-credit requests we need to check all current mid plus
711 * the implicit mids caused by the credit charge
712 * e.g. current mid = 15, charge 5 => mark 15-19 as used
715 for (i = 0; i <= (credit_charge-1); i++) {
716 uint64_t id = message_id + i;
717 bool ok;
719 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
720 (unsigned long long)message_id,
721 credit_charge,
722 (unsigned long long)id));
724 ok = smb2_validate_sequence_number(xconn, message_id, id);
725 if (!ok) {
726 return false;
730 /* substract used credits */
731 xconn->smb2.credits.granted -= credit_charge;
733 return true;
736 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
738 int count;
739 int idx;
741 count = req->in.vector_count;
743 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
744 /* It's not a SMB2 request */
745 return NT_STATUS_INVALID_PARAMETER;
748 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
749 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
750 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
751 const uint8_t *inhdr = NULL;
753 if (hdr->iov_len != SMB2_HDR_BODY) {
754 return NT_STATUS_INVALID_PARAMETER;
757 if (body->iov_len < 2) {
758 return NT_STATUS_INVALID_PARAMETER;
761 inhdr = (const uint8_t *)hdr->iov_base;
763 /* Check the SMB2 header */
764 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
765 return NT_STATUS_INVALID_PARAMETER;
768 if (!smb2_validate_message_id(req->xconn, inhdr)) {
769 return NT_STATUS_INVALID_PARAMETER;
773 return NT_STATUS_OK;
776 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
777 const struct iovec *in_vector,
778 struct iovec *out_vector)
780 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
781 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
782 uint16_t credit_charge = 1;
783 uint16_t credits_requested;
784 uint32_t out_flags;
785 uint16_t cmd;
786 NTSTATUS out_status;
787 uint16_t credits_granted = 0;
788 uint64_t credits_possible;
789 uint16_t current_max_credits;
792 * first we grant only 1/16th of the max range.
794 * Windows also starts with the 1/16th and then grants
795 * more later. I was only able to trigger higher
796 * values, when using a very high credit charge.
798 * TODO: scale up depending on load, free memory
799 * or other stuff.
800 * Maybe also on the relationship between number
801 * of requests and the used sequence number.
802 * Which means we would grant more credits
803 * for client which use multi credit requests.
805 current_max_credits = xconn->smb2.credits.max / 16;
806 current_max_credits = MAX(current_max_credits, 1);
808 if (xconn->smb2.credits.multicredit) {
809 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
810 credit_charge = MAX(credit_charge, 1);
813 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
814 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
815 credits_requested = MAX(credits_requested, 1);
816 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
817 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
819 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
821 if (xconn->smb2.credits.max < credit_charge) {
822 smbd_server_connection_terminate(xconn,
823 "client error: credit charge > max credits\n");
824 return;
827 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
829 * In case we already send an async interim
830 * response, we should not grant
831 * credits on the final response.
833 credits_granted = 0;
834 } else {
835 uint16_t additional_possible =
836 xconn->smb2.credits.max - credit_charge;
837 uint16_t additional_max = 0;
838 uint16_t additional_credits = credits_requested - 1;
840 switch (cmd) {
841 case SMB2_OP_NEGPROT:
842 break;
843 case SMB2_OP_SESSSETUP:
845 * Windows 2012 RC1 starts to grant
846 * additional credits
847 * with a successful session setup
849 if (NT_STATUS_IS_OK(out_status)) {
850 additional_max = 32;
852 break;
853 default:
855 * We match windows and only grant additional credits
856 * in chunks of 32.
858 additional_max = 32;
859 break;
862 additional_max = MIN(additional_max, additional_possible);
863 additional_credits = MIN(additional_credits, additional_max);
865 credits_granted = credit_charge + additional_credits;
869 * sequence numbers should not wrap
871 * 1. calculate the possible credits until
872 * the sequence numbers start to wrap on 64-bit.
874 * 2. UINT64_MAX is used for Break Notifications.
876 * 2. truncate the possible credits to the maximum
877 * credits we want to grant to the client in total.
879 * 3. remove the range we'll already granted to the client
880 * this makes sure the client consumes the lowest sequence
881 * number, before we can grant additional credits.
883 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
884 if (credits_possible > 0) {
885 /* remove UINT64_MAX */
886 credits_possible -= 1;
888 credits_possible = MIN(credits_possible, current_max_credits);
889 credits_possible -= xconn->smb2.credits.seq_range;
891 credits_granted = MIN(credits_granted, credits_possible);
893 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
894 xconn->smb2.credits.granted += credits_granted;
895 xconn->smb2.credits.seq_range += credits_granted;
897 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
898 "granted %u, current possible/max %u/%u, "
899 "total granted/max/low/range %u/%u/%llu/%u\n",
900 (unsigned int)credits_requested,
901 (unsigned int)credit_charge,
902 (unsigned int)credits_granted,
903 (unsigned int)credits_possible,
904 (unsigned int)current_max_credits,
905 (unsigned int)xconn->smb2.credits.granted,
906 (unsigned int)xconn->smb2.credits.max,
907 (unsigned long long)xconn->smb2.credits.seq_low,
908 (unsigned int)xconn->smb2.credits.seq_range));
911 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
912 struct smbd_smb2_request *outreq)
914 int count, idx;
915 uint16_t total_credits = 0;
917 count = outreq->out.vector_count;
919 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
920 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
921 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
922 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
924 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
926 /* To match Windows, count up what we
927 just granted. */
928 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
929 /* Set to zero in all but the last reply. */
930 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
931 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
932 } else {
933 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
938 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
940 if (req->current_idx <= 1) {
941 if (size <= sizeof(req->out._body)) {
942 return data_blob_const(req->out._body, size);
946 return data_blob_talloc(req, NULL, size);
949 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
951 struct smbXsrv_connection *xconn = req->xconn;
952 TALLOC_CTX *mem_ctx;
953 struct iovec *vector;
954 int count;
955 int idx;
956 bool ok;
958 count = req->in.vector_count;
959 if (count <= ARRAY_SIZE(req->out._vector)) {
960 mem_ctx = req;
961 vector = req->out._vector;
962 } else {
963 vector = talloc_zero_array(req, struct iovec, count);
964 if (vector == NULL) {
965 return NT_STATUS_NO_MEMORY;
967 mem_ctx = vector;
970 vector[0].iov_base = req->out.nbt_hdr;
971 vector[0].iov_len = 4;
972 SIVAL(req->out.nbt_hdr, 0, 0);
974 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
975 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
976 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
977 uint8_t *outhdr = NULL;
978 uint8_t *outbody = NULL;
979 uint32_t next_command_ofs = 0;
980 struct iovec *current = &vector[idx];
982 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
983 /* we have a next command -
984 * setup for the error case. */
985 next_command_ofs = SMB2_HDR_BODY + 9;
988 if (idx == 1) {
989 outhdr = req->out._hdr;
990 } else {
991 outhdr = talloc_zero_array(mem_ctx, uint8_t,
992 OUTVEC_ALLOC_SIZE);
993 if (outhdr == NULL) {
994 return NT_STATUS_NO_MEMORY;
998 outbody = outhdr + SMB2_HDR_BODY;
1001 * SMBD_SMB2_TF_IOV_OFS might be used later
1003 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1004 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1006 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1007 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1009 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1010 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1012 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1013 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1015 /* setup the SMB2 header */
1016 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1017 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1018 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1019 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1020 SIVAL(outhdr, SMB2_HDR_STATUS,
1021 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1022 SSVAL(outhdr, SMB2_HDR_OPCODE,
1023 SVAL(inhdr, SMB2_HDR_OPCODE));
1024 SIVAL(outhdr, SMB2_HDR_FLAGS,
1025 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1026 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1027 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1028 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1029 SIVAL(outhdr, SMB2_HDR_PID,
1030 IVAL(inhdr, SMB2_HDR_PID));
1031 SIVAL(outhdr, SMB2_HDR_TID,
1032 IVAL(inhdr, SMB2_HDR_TID));
1033 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1034 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1035 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1036 inhdr + SMB2_HDR_SIGNATURE, 16);
1038 /* setup error body header */
1039 SSVAL(outbody, 0x00, 0x08 + 1);
1040 SSVAL(outbody, 0x02, 0);
1041 SIVAL(outbody, 0x04, 0);
1044 req->out.vector = vector;
1045 req->out.vector_count = count;
1047 /* setup the length of the NBT packet */
1048 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1049 if (!ok) {
1050 return NT_STATUS_INVALID_PARAMETER_MIX;
1053 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1055 return NT_STATUS_OK;
1058 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1059 const char *reason,
1060 const char *location)
1062 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1063 reason, location));
1064 exit_server_cleanly(reason);
1067 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1068 struct iovec *outvec,
1069 const struct iovec *srcvec)
1071 const uint8_t *srctf;
1072 size_t srctf_len;
1073 const uint8_t *srchdr;
1074 size_t srchdr_len;
1075 const uint8_t *srcbody;
1076 size_t srcbody_len;
1077 const uint8_t *expected_srcbody;
1078 const uint8_t *srcdyn;
1079 size_t srcdyn_len;
1080 const uint8_t *expected_srcdyn;
1081 uint8_t *dsttf;
1082 uint8_t *dsthdr;
1083 uint8_t *dstbody;
1084 uint8_t *dstdyn;
1086 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1087 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1088 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1089 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1090 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1091 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1092 expected_srcbody = srchdr + SMB2_HDR_BODY;
1093 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1094 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1095 expected_srcdyn = srcbody + 8;
1097 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1098 return false;
1101 if (srchdr_len != SMB2_HDR_BODY) {
1102 return false;
1105 if (srctf_len == SMB2_TF_HDR_SIZE) {
1106 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1107 if (dsttf == NULL) {
1108 return false;
1110 } else {
1111 dsttf = NULL;
1113 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1114 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1116 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1117 * be allocated with size OUTVEC_ALLOC_SIZE. */
1119 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1120 if (dsthdr == NULL) {
1121 return false;
1123 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1124 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1127 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1128 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1129 * then duplicate this. Else use talloc_memdup().
1132 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1133 dstbody = dsthdr + SMB2_HDR_BODY;
1134 } else {
1135 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1136 if (dstbody == NULL) {
1137 return false;
1140 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1141 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1144 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1145 * pointing to
1146 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1147 * then duplicate this. Else use talloc_memdup().
1150 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1151 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1152 } else if (srcdyn == NULL) {
1153 dstdyn = NULL;
1154 } else {
1155 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1156 if (dstdyn == NULL) {
1157 return false;
1160 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1161 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1163 return true;
1166 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1168 struct smbd_smb2_request *newreq = NULL;
1169 struct iovec *outvec = NULL;
1170 int count = req->out.vector_count;
1171 int i;
1172 bool ok;
1174 newreq = smbd_smb2_request_allocate(req->xconn);
1175 if (!newreq) {
1176 return NULL;
1179 newreq->sconn = req->sconn;
1180 newreq->xconn = req->xconn;
1181 newreq->session = req->session;
1182 newreq->do_encryption = req->do_encryption;
1183 newreq->do_signing = req->do_signing;
1184 newreq->current_idx = req->current_idx;
1186 outvec = talloc_zero_array(newreq, struct iovec, count);
1187 if (!outvec) {
1188 TALLOC_FREE(newreq);
1189 return NULL;
1191 newreq->out.vector = outvec;
1192 newreq->out.vector_count = count;
1194 /* Setup the outvec's identically to req. */
1195 outvec[0].iov_base = newreq->out.nbt_hdr;
1196 outvec[0].iov_len = 4;
1197 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1199 /* Setup the vectors identically to the ones in req. */
1200 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1201 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1202 break;
1206 if (i < count) {
1207 /* Alloc failed. */
1208 TALLOC_FREE(newreq);
1209 return NULL;
1212 ok = smb2_setup_nbt_length(newreq->out.vector,
1213 newreq->out.vector_count);
1214 if (!ok) {
1215 TALLOC_FREE(newreq);
1216 return NULL;
1219 return newreq;
1222 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1224 struct smbXsrv_connection *xconn = req->xconn;
1225 int first_idx = 1;
1226 struct iovec *firsttf = NULL;
1227 struct iovec *outhdr_v = NULL;
1228 uint8_t *outhdr = NULL;
1229 struct smbd_smb2_request *nreq = NULL;
1230 NTSTATUS status;
1231 bool ok;
1233 /* Create a new smb2 request we'll use
1234 for the interim return. */
1235 nreq = dup_smb2_req(req);
1236 if (!nreq) {
1237 return NT_STATUS_NO_MEMORY;
1240 /* Lose the last X out vectors. They're the
1241 ones we'll be using for the async reply. */
1242 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1244 ok = smb2_setup_nbt_length(nreq->out.vector,
1245 nreq->out.vector_count);
1246 if (!ok) {
1247 return NT_STATUS_INVALID_PARAMETER_MIX;
1250 /* Step back to the previous reply. */
1251 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1252 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1253 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1254 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1255 /* And end the chain. */
1256 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1258 /* Calculate outgoing credits */
1259 smb2_calculate_credits(req, nreq);
1261 if (DEBUGLEVEL >= 10) {
1262 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1263 (unsigned int)nreq->current_idx );
1264 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1265 (unsigned int)nreq->out.vector_count );
1266 print_req_vectors(nreq);
1270 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1271 * we need to sign/encrypt here with the last/first key we remembered
1273 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1274 status = smb2_signing_encrypt_pdu(req->first_key,
1275 xconn->smb2.server.cipher,
1276 firsttf,
1277 nreq->out.vector_count - first_idx);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 return status;
1281 } else if (req->last_key.length > 0) {
1282 status = smb2_signing_sign_pdu(req->last_key,
1283 xconn->protocol,
1284 outhdr_v,
1285 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 return status;
1291 nreq->queue_entry.mem_ctx = nreq;
1292 nreq->queue_entry.vector = nreq->out.vector;
1293 nreq->queue_entry.count = nreq->out.vector_count;
1294 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1295 xconn->smb2.send_queue_len++;
1297 status = smbd_smb2_flush_send_queue(xconn);
1298 if (!NT_STATUS_IS_OK(status)) {
1299 return status;
1302 return NT_STATUS_OK;
1305 struct smbd_smb2_request_pending_state {
1306 struct smbd_smb2_send_queue queue_entry;
1307 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1308 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1311 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1312 struct tevent_timer *te,
1313 struct timeval current_time,
1314 void *private_data);
1316 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1317 struct tevent_req *subreq,
1318 uint32_t defer_time)
1320 NTSTATUS status;
1321 struct timeval defer_endtime;
1322 uint8_t *outhdr = NULL;
1323 uint32_t flags;
1325 if (!tevent_req_is_in_progress(subreq)) {
1327 * This is a performance optimization,
1328 * it avoids one tevent_loop iteration,
1329 * which means we avoid one
1330 * talloc_stackframe_pool/talloc_free pair.
1332 tevent_req_notify_callback(subreq);
1333 return NT_STATUS_OK;
1336 req->subreq = subreq;
1337 subreq = NULL;
1339 if (req->async_te) {
1340 /* We're already async. */
1341 return NT_STATUS_OK;
1344 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1345 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1346 if (flags & SMB2_HDR_FLAG_ASYNC) {
1347 /* We're already async. */
1348 return NT_STATUS_OK;
1351 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1353 * We're trying to go async in a compound request
1354 * chain. This is only allowed for opens that cause an
1355 * oplock break or for the last operation in the
1356 * chain, otherwise it is not allowed. See
1357 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1359 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1361 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1363 * Cancel the outstanding request.
1365 bool ok = tevent_req_cancel(req->subreq);
1366 if (ok) {
1367 return NT_STATUS_OK;
1369 TALLOC_FREE(req->subreq);
1370 return smbd_smb2_request_error(req,
1371 NT_STATUS_INTERNAL_ERROR);
1375 if (DEBUGLEVEL >= 10) {
1376 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1377 (unsigned int)req->current_idx );
1378 print_req_vectors(req);
1381 if (req->current_idx > 1) {
1383 * We're going async in a compound
1384 * chain after the first request has
1385 * already been processed. Send an
1386 * interim response containing the
1387 * set of replies already generated.
1389 int idx = req->current_idx;
1391 status = smb2_send_async_interim_response(req);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 return status;
1395 if (req->first_key.length > 0) {
1396 data_blob_clear_free(&req->first_key);
1399 req->current_idx = 1;
1402 * Re-arrange the in.vectors to remove what
1403 * we just sent.
1405 memmove(&req->in.vector[1],
1406 &req->in.vector[idx],
1407 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1408 req->in.vector_count = 1 + (req->in.vector_count - idx);
1410 /* Re-arrange the out.vectors to match. */
1411 memmove(&req->out.vector[1],
1412 &req->out.vector[idx],
1413 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1414 req->out.vector_count = 1 + (req->out.vector_count - idx);
1416 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1418 * We only have one remaining request as
1419 * we've processed everything else.
1420 * This is no longer a compound request.
1422 req->compound_related = false;
1423 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1424 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1425 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1428 if (req->last_key.length > 0) {
1429 data_blob_clear_free(&req->last_key);
1432 defer_endtime = timeval_current_ofs_usec(defer_time);
1433 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1434 req, defer_endtime,
1435 smbd_smb2_request_pending_timer,
1436 req);
1437 if (req->async_te == NULL) {
1438 return NT_STATUS_NO_MEMORY;
1441 return NT_STATUS_OK;
1444 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1445 struct smbXsrv_connection *xconn)
1447 struct smbXsrv_channel_global0 *c = NULL;
1448 NTSTATUS status;
1449 DATA_BLOB key = data_blob_null;
1451 status = smbXsrv_session_find_channel(session, xconn, &c);
1452 if (NT_STATUS_IS_OK(status)) {
1453 key = c->signing_key;
1456 if (key.length == 0) {
1457 key = session->global->signing_key;
1460 return key;
1463 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1464 uint64_t *new_nonce_high,
1465 uint64_t *new_nonce_low)
1467 uint64_t nonce_high;
1468 uint64_t nonce_low;
1470 session->nonce_low += 1;
1471 if (session->nonce_low == 0) {
1472 session->nonce_low += 1;
1473 session->nonce_high += 1;
1477 * CCM and GCM algorithms must never have their
1478 * nonce wrap, or the security of the whole
1479 * communication and the keys is destroyed.
1480 * We must drop the connection once we have
1481 * transfered too much data.
1483 * NOTE: We assume nonces greater than 8 bytes.
1485 if (session->nonce_high >= session->nonce_high_max) {
1486 return NT_STATUS_ENCRYPTION_FAILED;
1489 nonce_high = session->nonce_high_random;
1490 nonce_high += session->nonce_high;
1491 nonce_low = session->nonce_low;
1493 *new_nonce_high = nonce_high;
1494 *new_nonce_low = nonce_low;
1495 return NT_STATUS_OK;
1498 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1499 struct tevent_timer *te,
1500 struct timeval current_time,
1501 void *private_data)
1503 struct smbd_smb2_request *req =
1504 talloc_get_type_abort(private_data,
1505 struct smbd_smb2_request);
1506 struct smbXsrv_connection *xconn = req->xconn;
1507 struct smbd_smb2_request_pending_state *state = NULL;
1508 uint8_t *outhdr = NULL;
1509 const uint8_t *inhdr = NULL;
1510 uint8_t *tf = NULL;
1511 size_t tf_len = 0;
1512 uint8_t *hdr = NULL;
1513 uint8_t *body = NULL;
1514 uint8_t *dyn = NULL;
1515 uint32_t flags = 0;
1516 uint64_t session_id = 0;
1517 uint64_t message_id = 0;
1518 uint64_t nonce_high = 0;
1519 uint64_t nonce_low = 0;
1520 uint64_t async_id = 0;
1521 NTSTATUS status;
1522 bool ok;
1524 TALLOC_FREE(req->async_te);
1526 /* Ensure our final reply matches the interim one. */
1527 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1528 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1529 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1530 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1531 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1533 async_id = message_id; /* keep it simple for now... */
1535 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1536 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1538 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1539 "going async\n",
1540 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1541 (unsigned long long)async_id ));
1544 * What we send is identical to a smbd_smb2_request_error
1545 * packet with an error status of STATUS_PENDING. Make use
1546 * of this fact sometime when refactoring. JRA.
1549 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1550 if (state == NULL) {
1551 smbd_server_connection_terminate(xconn,
1552 nt_errstr(NT_STATUS_NO_MEMORY));
1553 return;
1556 tf = state->buf + NBT_HDR_SIZE;
1557 tf_len = SMB2_TF_HDR_SIZE;
1559 hdr = tf + SMB2_TF_HDR_SIZE;
1560 body = hdr + SMB2_HDR_BODY;
1561 dyn = body + 8;
1563 if (req->do_encryption) {
1564 status = smb2_get_new_nonce(req->session,
1565 &nonce_high,
1566 &nonce_low);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 smbd_server_connection_terminate(xconn,
1569 nt_errstr(status));
1570 return;
1574 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1575 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1576 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1577 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1579 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1580 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1581 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1582 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1583 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1585 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1586 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1587 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1588 SBVAL(hdr, SMB2_HDR_PID, async_id);
1589 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1590 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1591 memcpy(hdr+SMB2_HDR_SIGNATURE,
1592 outhdr+SMB2_HDR_SIGNATURE, 16);
1594 SSVAL(body, 0x00, 0x08 + 1);
1596 SCVAL(body, 0x02, 0);
1597 SCVAL(body, 0x03, 0);
1598 SIVAL(body, 0x04, 0);
1599 /* Match W2K8R2... */
1600 SCVAL(dyn, 0x00, 0x21);
1602 state->vector[0].iov_base = (void *)state->buf;
1603 state->vector[0].iov_len = NBT_HDR_SIZE;
1605 if (req->do_encryption) {
1606 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1607 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1608 } else {
1609 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1610 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1613 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1614 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1616 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1617 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1619 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1620 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1622 ok = smb2_setup_nbt_length(state->vector,
1623 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1624 if (!ok) {
1625 smbd_server_connection_terminate(
1626 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1627 return;
1630 /* Ensure we correctly go through crediting. Grant
1631 the credits now, and zero credits on the final
1632 response. */
1633 smb2_set_operation_credit(req->xconn,
1634 SMBD_SMB2_IN_HDR_IOV(req),
1635 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1637 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1639 if (DEBUGLVL(10)) {
1640 int i;
1642 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1643 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1644 (unsigned int)i,
1645 (unsigned int)ARRAY_SIZE(state->vector),
1646 (unsigned int)state->vector[i].iov_len);
1650 if (req->do_encryption) {
1651 struct smbXsrv_session *x = req->session;
1652 DATA_BLOB encryption_key = x->global->encryption_key;
1654 status = smb2_signing_encrypt_pdu(encryption_key,
1655 xconn->smb2.server.cipher,
1656 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1657 SMBD_SMB2_NUM_IOV_PER_REQ);
1658 if (!NT_STATUS_IS_OK(status)) {
1659 smbd_server_connection_terminate(xconn,
1660 nt_errstr(status));
1661 return;
1663 } else if (req->do_signing) {
1664 struct smbXsrv_session *x = req->session;
1665 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1667 status = smb2_signing_sign_pdu(signing_key,
1668 xconn->protocol,
1669 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1670 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1671 if (!NT_STATUS_IS_OK(status)) {
1672 smbd_server_connection_terminate(xconn,
1673 nt_errstr(status));
1674 return;
1678 state->queue_entry.mem_ctx = state;
1679 state->queue_entry.vector = state->vector;
1680 state->queue_entry.count = ARRAY_SIZE(state->vector);
1681 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1682 xconn->smb2.send_queue_len++;
1684 status = smbd_smb2_flush_send_queue(xconn);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 smbd_server_connection_terminate(xconn,
1687 nt_errstr(status));
1688 return;
1692 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1694 struct smbXsrv_connection *xconn = req->xconn;
1695 struct smbd_smb2_request *cur;
1696 const uint8_t *inhdr;
1697 uint32_t flags;
1698 uint64_t search_message_id;
1699 uint64_t search_async_id;
1700 uint64_t found_id;
1702 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1704 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1705 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1706 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1709 * We don't need the request anymore cancel requests never
1710 * have a response.
1712 * We defer the TALLOC_FREE(req) to the caller.
1714 DLIST_REMOVE(xconn->smb2.requests, req);
1716 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1717 const uint8_t *outhdr;
1718 uint64_t message_id;
1719 uint64_t async_id;
1721 if (cur->compound_related) {
1723 * Never cancel anything in a compound request.
1724 * Way too hard to deal with the result.
1726 continue;
1729 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1731 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1732 async_id = BVAL(outhdr, SMB2_HDR_PID);
1734 if (flags & SMB2_HDR_FLAG_ASYNC) {
1735 if (search_async_id == async_id) {
1736 found_id = async_id;
1737 break;
1739 } else {
1740 if (search_message_id == message_id) {
1741 found_id = message_id;
1742 break;
1747 if (cur && cur->subreq) {
1748 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1749 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1750 "cancel opcode[%s] mid %llu\n",
1751 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1752 (unsigned long long)found_id ));
1753 tevent_req_cancel(cur->subreq);
1756 return NT_STATUS_OK;
1759 /*************************************************************
1760 Ensure an incoming tid is a valid one for us to access.
1761 Change to the associated uid credentials and chdir to the
1762 valid tid directory.
1763 *************************************************************/
1765 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1767 const uint8_t *inhdr;
1768 uint32_t in_flags;
1769 uint32_t in_tid;
1770 struct smbXsrv_tcon *tcon;
1771 NTSTATUS status;
1772 NTTIME now = timeval_to_nttime(&req->request_time);
1774 req->tcon = NULL;
1776 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1778 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1779 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1781 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1782 in_tid = req->last_tid;
1785 req->last_tid = 0;
1787 status = smb2srv_tcon_lookup(req->session,
1788 in_tid, now, &tcon);
1789 if (!NT_STATUS_IS_OK(status)) {
1790 return status;
1793 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1794 return NT_STATUS_ACCESS_DENIED;
1797 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1798 if (!set_current_service(tcon->compat, 0, true)) {
1799 return NT_STATUS_ACCESS_DENIED;
1802 req->tcon = tcon;
1803 req->last_tid = in_tid;
1805 return NT_STATUS_OK;
1808 /*************************************************************
1809 Ensure an incoming session_id is a valid one for us to access.
1810 *************************************************************/
1812 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1814 const uint8_t *inhdr;
1815 uint32_t in_flags;
1816 uint16_t in_opcode;
1817 uint64_t in_session_id;
1818 struct smbXsrv_session *session = NULL;
1819 struct auth_session_info *session_info;
1820 NTSTATUS status;
1821 NTTIME now = timeval_to_nttime(&req->request_time);
1823 req->session = NULL;
1824 req->tcon = NULL;
1826 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1828 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1829 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1830 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1832 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1833 in_session_id = req->last_session_id;
1836 req->last_session_id = 0;
1838 /* look an existing session up */
1839 switch (in_opcode) {
1840 case SMB2_OP_SESSSETUP:
1842 * For a session bind request, we don't have the
1843 * channel set up at this point yet, so we defer
1844 * the verification that the connection belongs
1845 * to the session to the session setup code, which
1846 * can look at the session binding flags.
1848 status = smb2srv_session_lookup_client(req->xconn->client,
1849 in_session_id, now,
1850 &session);
1851 break;
1852 default:
1853 status = smb2srv_session_lookup_conn(req->xconn,
1854 in_session_id, now,
1855 &session);
1856 break;
1858 if (session) {
1859 req->session = session;
1860 req->last_session_id = in_session_id;
1862 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1863 switch (in_opcode) {
1864 case SMB2_OP_SESSSETUP:
1865 status = NT_STATUS_OK;
1866 break;
1867 default:
1868 break;
1871 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1872 switch (in_opcode) {
1873 case SMB2_OP_TCON:
1874 case SMB2_OP_CREATE:
1875 case SMB2_OP_GETINFO:
1876 case SMB2_OP_SETINFO:
1877 return NT_STATUS_INVALID_HANDLE;
1878 default:
1880 * Notice the check for
1881 * (session_info == NULL)
1882 * below.
1884 status = NT_STATUS_OK;
1885 break;
1888 if (!NT_STATUS_IS_OK(status)) {
1889 return status;
1892 session_info = session->global->auth_session_info;
1893 if (session_info == NULL) {
1894 return NT_STATUS_INVALID_HANDLE;
1897 if (in_session_id != req->xconn->client->last_session_id) {
1898 req->xconn->client->last_session_id = in_session_id;
1899 set_current_user_info(session_info->unix_info->sanitized_username,
1900 session_info->unix_info->unix_name,
1901 session_info->info->domain_name);
1904 return NT_STATUS_OK;
1907 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1908 uint32_t data_length)
1910 struct smbXsrv_connection *xconn = req->xconn;
1911 uint16_t needed_charge;
1912 uint16_t credit_charge = 1;
1913 const uint8_t *inhdr;
1915 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1917 if (xconn->smb2.credits.multicredit) {
1918 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1919 credit_charge = MAX(credit_charge, 1);
1922 needed_charge = (data_length - 1)/ 65536 + 1;
1924 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1925 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1926 credit_charge, needed_charge));
1928 if (needed_charge > credit_charge) {
1929 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1930 credit_charge, needed_charge));
1931 return NT_STATUS_INVALID_PARAMETER;
1934 return NT_STATUS_OK;
1937 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1938 size_t expected_body_size)
1940 struct iovec *inhdr_v;
1941 const uint8_t *inhdr;
1942 uint16_t opcode;
1943 const uint8_t *inbody;
1944 size_t body_size;
1945 size_t min_dyn_size = expected_body_size & 0x00000001;
1946 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1949 * The following should be checked already.
1951 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1952 return NT_STATUS_INTERNAL_ERROR;
1954 if (req->current_idx > max_idx) {
1955 return NT_STATUS_INTERNAL_ERROR;
1958 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1959 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1960 return NT_STATUS_INTERNAL_ERROR;
1962 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1963 return NT_STATUS_INTERNAL_ERROR;
1966 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1967 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1969 switch (opcode) {
1970 case SMB2_OP_IOCTL:
1971 case SMB2_OP_GETINFO:
1972 min_dyn_size = 0;
1973 break;
1974 case SMB2_OP_WRITE:
1975 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1976 if (req->smb1req->unread_bytes < min_dyn_size) {
1977 return NT_STATUS_INVALID_PARAMETER;
1980 min_dyn_size = 0;
1982 break;
1986 * Now check the expected body size,
1987 * where the last byte might be in the
1988 * dynamic section..
1990 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1991 return NT_STATUS_INVALID_PARAMETER;
1993 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1994 return NT_STATUS_INVALID_PARAMETER;
1997 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1999 body_size = SVAL(inbody, 0x00);
2000 if (body_size != expected_body_size) {
2001 return NT_STATUS_INVALID_PARAMETER;
2004 return NT_STATUS_OK;
2007 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2009 struct smbXsrv_connection *xconn = req->xconn;
2010 const struct smbd_smb2_dispatch_table *call = NULL;
2011 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2012 const uint8_t *inhdr;
2013 uint16_t opcode;
2014 uint32_t flags;
2015 uint64_t mid;
2016 NTSTATUS status;
2017 NTSTATUS session_status;
2018 uint32_t allowed_flags;
2019 NTSTATUS return_value;
2020 struct smbXsrv_session *x = NULL;
2021 bool signing_required = false;
2022 bool encryption_desired = false;
2023 bool encryption_required = false;
2025 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2027 DO_PROFILE_INC(request);
2029 /* TODO: verify more things */
2031 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2032 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2033 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2034 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2035 smb2_opcode_name(opcode),
2036 (unsigned long long)mid));
2038 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2040 * once the protocol is negotiated
2041 * SMB2_OP_NEGPROT is not allowed anymore
2043 if (opcode == SMB2_OP_NEGPROT) {
2044 /* drop the connection */
2045 return NT_STATUS_INVALID_PARAMETER;
2047 } else {
2049 * if the protocol is not negotiated yet
2050 * only SMB2_OP_NEGPROT is allowed.
2052 if (opcode != SMB2_OP_NEGPROT) {
2053 /* drop the connection */
2054 return NT_STATUS_INVALID_PARAMETER;
2059 * Check if the client provided a valid session id,
2060 * if so smbd_smb2_request_check_session() calls
2061 * set_current_user_info().
2063 * As some command don't require a valid session id
2064 * we defer the check of the session_status
2066 session_status = smbd_smb2_request_check_session(req);
2067 x = req->session;
2068 if (x != NULL) {
2069 signing_required = x->global->signing_required;
2070 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2071 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
2074 req->do_signing = false;
2075 req->do_encryption = false;
2076 req->was_encrypted = false;
2077 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2078 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2079 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2081 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2082 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2083 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2084 (unsigned long long)x->global->session_wire_id,
2085 (unsigned long long)tf_session_id));
2087 * TODO: windows allows this...
2088 * should we drop the connection?
2090 * For now we just return ACCESS_DENIED
2091 * (Windows clients never trigger this)
2092 * and wait for an update of [MS-SMB2].
2094 return smbd_smb2_request_error(req,
2095 NT_STATUS_ACCESS_DENIED);
2098 req->was_encrypted = true;
2101 if (encryption_required && !req->was_encrypted) {
2102 return smbd_smb2_request_error(req,
2103 NT_STATUS_ACCESS_DENIED);
2106 call = smbd_smb2_call(opcode);
2107 if (call == NULL) {
2108 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2111 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2112 SMB2_HDR_FLAG_SIGNED |
2113 SMB2_HDR_FLAG_DFS;
2114 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2115 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2117 if (opcode == SMB2_OP_NEGPROT) {
2118 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2119 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2122 if (opcode == SMB2_OP_CANCEL) {
2123 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2125 if ((flags & ~allowed_flags) != 0) {
2126 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2129 if (flags & SMB2_HDR_FLAG_CHAINED) {
2131 * This check is mostly for giving the correct error code
2132 * for compounded requests.
2134 if (!NT_STATUS_IS_OK(session_status)) {
2135 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2137 } else {
2138 req->compat_chain_fsp = NULL;
2141 if (req->was_encrypted) {
2142 signing_required = false;
2143 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2144 DATA_BLOB signing_key = data_blob_null;
2146 if (x == NULL) {
2148 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2149 * If the SMB2 header of the SMB2 NEGOTIATE
2150 * request has the SMB2_FLAGS_SIGNED bit set in the
2151 * Flags field, the server MUST fail the request
2152 * with STATUS_INVALID_PARAMETER.
2154 * Microsoft test tool checks this.
2157 if ((opcode == SMB2_OP_NEGPROT) &&
2158 (flags & SMB2_HDR_FLAG_SIGNED)) {
2159 status = NT_STATUS_INVALID_PARAMETER;
2160 } else {
2161 status = NT_STATUS_USER_SESSION_DELETED;
2163 return smbd_smb2_request_error(req, status);
2166 signing_key = smbd_smb2_signing_key(x, xconn);
2169 * If we have a signing key, we should
2170 * sign the response
2172 if (signing_key.length > 0) {
2173 req->do_signing = true;
2176 status = smb2_signing_check_pdu(signing_key,
2177 xconn->protocol,
2178 SMBD_SMB2_IN_HDR_IOV(req),
2179 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 return smbd_smb2_request_error(req, status);
2185 * Now that we know the request was correctly signed
2186 * we have to sign the response too.
2188 req->do_signing = true;
2190 if (!NT_STATUS_IS_OK(session_status)) {
2191 return smbd_smb2_request_error(req, session_status);
2193 } else if (opcode == SMB2_OP_CANCEL) {
2194 /* Cancel requests are allowed to skip the signing */
2195 } else if (signing_required) {
2197 * If signing is required we try to sign
2198 * a possible error response
2200 req->do_signing = true;
2201 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2204 if (flags & SMB2_HDR_FLAG_CHAINED) {
2205 req->compound_related = true;
2208 if (call->need_session) {
2209 if (!NT_STATUS_IS_OK(session_status)) {
2210 return smbd_smb2_request_error(req, session_status);
2214 if (call->need_tcon) {
2215 SMB_ASSERT(call->need_session);
2218 * This call needs to be run as user.
2220 * smbd_smb2_request_check_tcon()
2221 * calls change_to_user() on success.
2223 status = smbd_smb2_request_check_tcon(req);
2224 if (!NT_STATUS_IS_OK(status)) {
2225 return smbd_smb2_request_error(req, status);
2227 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2228 encryption_desired = true;
2230 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
2231 encryption_required = true;
2233 if (encryption_required && !req->was_encrypted) {
2234 return smbd_smb2_request_error(req,
2235 NT_STATUS_ACCESS_DENIED);
2239 if (req->was_encrypted || encryption_desired) {
2240 req->do_encryption = true;
2243 if (call->fileid_ofs != 0) {
2244 size_t needed = call->fileid_ofs + 16;
2245 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2246 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2247 uint64_t file_id_persistent;
2248 uint64_t file_id_volatile;
2249 struct files_struct *fsp;
2251 SMB_ASSERT(call->need_tcon);
2253 if (needed > body_size) {
2254 return smbd_smb2_request_error(req,
2255 NT_STATUS_INVALID_PARAMETER);
2258 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2259 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2261 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2262 if (fsp == NULL) {
2263 if (!call->allow_invalid_fileid) {
2264 return smbd_smb2_request_error(req,
2265 NT_STATUS_FILE_CLOSED);
2268 if (file_id_persistent != UINT64_MAX) {
2269 return smbd_smb2_request_error(req,
2270 NT_STATUS_FILE_CLOSED);
2272 if (file_id_volatile != UINT64_MAX) {
2273 return smbd_smb2_request_error(req,
2274 NT_STATUS_FILE_CLOSED);
2279 if (call->as_root) {
2280 SMB_ASSERT(call->fileid_ofs == 0);
2281 /* This call needs to be run as root */
2282 change_to_root_user();
2283 } else {
2284 SMB_ASSERT(call->need_tcon);
2287 #define _INBYTES(_r) \
2288 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2290 switch (opcode) {
2291 case SMB2_OP_NEGPROT:
2292 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2293 req->profile, _INBYTES(req));
2294 return_value = smbd_smb2_request_process_negprot(req);
2295 break;
2297 case SMB2_OP_SESSSETUP:
2298 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2299 req->profile, _INBYTES(req));
2300 return_value = smbd_smb2_request_process_sesssetup(req);
2301 break;
2303 case SMB2_OP_LOGOFF:
2304 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2305 req->profile, _INBYTES(req));
2306 return_value = smbd_smb2_request_process_logoff(req);
2307 break;
2309 case SMB2_OP_TCON:
2310 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2311 req->profile, _INBYTES(req));
2312 return_value = smbd_smb2_request_process_tcon(req);
2313 break;
2315 case SMB2_OP_TDIS:
2316 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2317 req->profile, _INBYTES(req));
2318 return_value = smbd_smb2_request_process_tdis(req);
2319 break;
2321 case SMB2_OP_CREATE:
2322 if (req->subreq == NULL) {
2323 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2324 req->profile, _INBYTES(req));
2325 } else {
2326 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2328 return_value = smbd_smb2_request_process_create(req);
2329 break;
2331 case SMB2_OP_CLOSE:
2332 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2333 req->profile, _INBYTES(req));
2334 return_value = smbd_smb2_request_process_close(req);
2335 break;
2337 case SMB2_OP_FLUSH:
2338 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2339 req->profile, _INBYTES(req));
2340 return_value = smbd_smb2_request_process_flush(req);
2341 break;
2343 case SMB2_OP_READ:
2344 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2345 req->profile, _INBYTES(req));
2346 return_value = smbd_smb2_request_process_read(req);
2347 break;
2349 case SMB2_OP_WRITE:
2350 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2351 req->profile, _INBYTES(req));
2352 return_value = smbd_smb2_request_process_write(req);
2353 break;
2355 case SMB2_OP_LOCK:
2356 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2357 req->profile, _INBYTES(req));
2358 return_value = smbd_smb2_request_process_lock(req);
2359 break;
2361 case SMB2_OP_IOCTL:
2362 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2363 req->profile, _INBYTES(req));
2364 return_value = smbd_smb2_request_process_ioctl(req);
2365 break;
2367 case SMB2_OP_CANCEL:
2368 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2369 req->profile, _INBYTES(req));
2370 return_value = smbd_smb2_request_process_cancel(req);
2371 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2374 * We don't need the request anymore cancel requests never
2375 * have a response.
2377 * smbd_smb2_request_process_cancel() already called
2378 * DLIST_REMOVE(xconn->smb2.requests, req);
2380 TALLOC_FREE(req);
2382 break;
2384 case SMB2_OP_KEEPALIVE:
2385 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2386 req->profile, _INBYTES(req));
2387 return_value = smbd_smb2_request_process_keepalive(req);
2388 break;
2390 case SMB2_OP_QUERY_DIRECTORY:
2391 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2392 req->profile, _INBYTES(req));
2393 return_value = smbd_smb2_request_process_query_directory(req);
2394 break;
2396 case SMB2_OP_NOTIFY:
2397 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2398 req->profile, _INBYTES(req));
2399 return_value = smbd_smb2_request_process_notify(req);
2400 break;
2402 case SMB2_OP_GETINFO:
2403 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2404 req->profile, _INBYTES(req));
2405 return_value = smbd_smb2_request_process_getinfo(req);
2406 break;
2408 case SMB2_OP_SETINFO:
2409 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2410 req->profile, _INBYTES(req));
2411 return_value = smbd_smb2_request_process_setinfo(req);
2412 break;
2414 case SMB2_OP_BREAK:
2415 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2416 req->profile, _INBYTES(req));
2417 return_value = smbd_smb2_request_process_break(req);
2418 break;
2420 default:
2421 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2422 break;
2424 return return_value;
2427 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2429 struct smbXsrv_connection *xconn = req->xconn;
2430 int first_idx = 1;
2431 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2432 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2433 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2434 NTSTATUS status;
2435 bool ok;
2437 req->subreq = NULL;
2438 TALLOC_FREE(req->async_te);
2440 if (req->do_encryption &&
2441 (firsttf->iov_len == 0) &&
2442 (req->first_key.length == 0) &&
2443 (req->session != NULL) &&
2444 (req->session->global->encryption_key.length != 0))
2446 DATA_BLOB encryption_key = req->session->global->encryption_key;
2447 uint8_t *tf;
2448 uint64_t session_id = req->session->global->session_wire_id;
2449 uint64_t nonce_high;
2450 uint64_t nonce_low;
2452 status = smb2_get_new_nonce(req->session,
2453 &nonce_high,
2454 &nonce_low);
2455 if (!NT_STATUS_IS_OK(status)) {
2456 return status;
2460 * We need to place the SMB2_TRANSFORM header before the
2461 * first SMB2 header
2465 * we need to remember the encryption key
2466 * and defer the signing/encryption until
2467 * we are sure that we do not change
2468 * the header again.
2470 req->first_key = data_blob_dup_talloc(req, encryption_key);
2471 if (req->first_key.data == NULL) {
2472 return NT_STATUS_NO_MEMORY;
2475 tf = talloc_zero_array(req, uint8_t,
2476 SMB2_TF_HDR_SIZE);
2477 if (tf == NULL) {
2478 return NT_STATUS_NO_MEMORY;
2481 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2482 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2483 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2484 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2486 firsttf->iov_base = (void *)tf;
2487 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2490 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2491 (req->last_key.length > 0) &&
2492 (firsttf->iov_len == 0))
2494 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2495 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2498 * As we are sure the header of the last request in the
2499 * compound chain will not change, we can to sign here
2500 * with the last signing key we remembered.
2502 status = smb2_signing_sign_pdu(req->last_key,
2503 xconn->protocol,
2504 lasthdr,
2505 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 return status;
2510 if (req->last_key.length > 0) {
2511 data_blob_clear_free(&req->last_key);
2514 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2515 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2517 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2519 if (req->current_idx < req->out.vector_count) {
2521 * We must process the remaining compound
2522 * SMB2 requests before any new incoming SMB2
2523 * requests. This is because incoming SMB2
2524 * requests may include a cancel for a
2525 * compound request we haven't processed
2526 * yet.
2528 struct tevent_immediate *im = tevent_create_immediate(req);
2529 if (!im) {
2530 return NT_STATUS_NO_MEMORY;
2533 if (req->do_signing && firsttf->iov_len == 0) {
2534 struct smbXsrv_session *x = req->session;
2535 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2538 * we need to remember the signing key
2539 * and defer the signing until
2540 * we are sure that we do not change
2541 * the header again.
2543 req->last_key = data_blob_dup_talloc(req, signing_key);
2544 if (req->last_key.data == NULL) {
2545 return NT_STATUS_NO_MEMORY;
2549 tevent_schedule_immediate(im,
2550 req->sconn->ev_ctx,
2551 smbd_smb2_request_dispatch_immediate,
2552 req);
2553 return NT_STATUS_OK;
2556 if (req->compound_related) {
2557 req->compound_related = false;
2560 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2561 if (!ok) {
2562 return NT_STATUS_INVALID_PARAMETER_MIX;
2565 /* Set credit for these operations (zero credits if this
2566 is a final reply for an async operation). */
2567 smb2_calculate_credits(req, req);
2570 * now check if we need to sign the current response
2572 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2573 status = smb2_signing_encrypt_pdu(req->first_key,
2574 xconn->smb2.server.cipher,
2575 firsttf,
2576 req->out.vector_count - first_idx);
2577 if (!NT_STATUS_IS_OK(status)) {
2578 return status;
2580 } else if (req->do_signing) {
2581 struct smbXsrv_session *x = req->session;
2582 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2584 status = smb2_signing_sign_pdu(signing_key,
2585 xconn->protocol,
2586 outhdr,
2587 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2588 if (!NT_STATUS_IS_OK(status)) {
2589 return status;
2592 if (req->first_key.length > 0) {
2593 data_blob_clear_free(&req->first_key);
2596 if (req->preauth != NULL) {
2597 struct hc_sha512state sctx;
2598 int i;
2600 samba_SHA512_Init(&sctx);
2601 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2602 sizeof(req->preauth->sha512_value));
2603 for (i = 1; i < req->in.vector_count; i++) {
2604 samba_SHA512_Update(&sctx,
2605 req->in.vector[i].iov_base,
2606 req->in.vector[i].iov_len);
2608 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2610 samba_SHA512_Init(&sctx);
2611 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2612 sizeof(req->preauth->sha512_value));
2613 for (i = 1; i < req->out.vector_count; i++) {
2614 samba_SHA512_Update(&sctx,
2615 req->out.vector[i].iov_base,
2616 req->out.vector[i].iov_len);
2618 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2620 req->preauth = NULL;
2623 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2624 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2625 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2626 /* Dynamic part is NULL. Chop it off,
2627 We're going to send it via sendfile. */
2628 req->out.vector_count -= 1;
2632 * We're done with this request -
2633 * move it off the "being processed" queue.
2635 DLIST_REMOVE(xconn->smb2.requests, req);
2637 req->queue_entry.mem_ctx = req;
2638 req->queue_entry.vector = req->out.vector;
2639 req->queue_entry.count = req->out.vector_count;
2640 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2641 xconn->smb2.send_queue_len++;
2643 status = smbd_smb2_flush_send_queue(xconn);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 return status;
2648 return NT_STATUS_OK;
2651 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2653 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2654 struct tevent_immediate *im,
2655 void *private_data)
2657 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2658 struct smbd_smb2_request);
2659 struct smbXsrv_connection *xconn = req->xconn;
2660 NTSTATUS status;
2662 TALLOC_FREE(im);
2664 if (DEBUGLEVEL >= 10) {
2665 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2666 req->current_idx, req->in.vector_count));
2667 print_req_vectors(req);
2670 status = smbd_smb2_request_dispatch(req);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 smbd_server_connection_terminate(xconn, nt_errstr(status));
2673 return;
2676 status = smbd_smb2_request_next_incoming(xconn);
2677 if (!NT_STATUS_IS_OK(status)) {
2678 smbd_server_connection_terminate(xconn, nt_errstr(status));
2679 return;
2683 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2684 NTSTATUS status,
2685 DATA_BLOB body, DATA_BLOB *dyn,
2686 const char *location)
2688 uint8_t *outhdr;
2689 struct iovec *outbody_v;
2690 struct iovec *outdyn_v;
2691 uint32_t next_command_ofs;
2693 DEBUG(10,("smbd_smb2_request_done_ex: "
2694 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2695 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2696 dyn ? "yes": "no",
2697 (unsigned int)(dyn ? dyn->length : 0),
2698 location));
2700 if (body.length < 2) {
2701 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2704 if ((body.length % 2) != 0) {
2705 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2708 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2709 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2710 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2712 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2713 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2715 outbody_v->iov_base = (void *)body.data;
2716 outbody_v->iov_len = body.length;
2718 if (dyn) {
2719 outdyn_v->iov_base = (void *)dyn->data;
2720 outdyn_v->iov_len = dyn->length;
2721 } else {
2722 outdyn_v->iov_base = NULL;
2723 outdyn_v->iov_len = 0;
2727 * See if we need to recalculate the offset to the next response
2729 * Note that all responses may require padding (including the very last
2730 * one).
2732 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
2733 next_command_ofs = SMB2_HDR_BODY;
2734 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2735 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2738 if ((next_command_ofs % 8) != 0) {
2739 size_t pad_size = 8 - (next_command_ofs % 8);
2740 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2742 * if the dyn buffer is empty
2743 * we can use it to add padding
2745 uint8_t *pad;
2747 pad = talloc_zero_array(req,
2748 uint8_t, pad_size);
2749 if (pad == NULL) {
2750 return smbd_smb2_request_error(req,
2751 NT_STATUS_NO_MEMORY);
2754 outdyn_v->iov_base = (void *)pad;
2755 outdyn_v->iov_len = pad_size;
2756 } else {
2758 * For now we copy the dynamic buffer
2759 * and add the padding to the new buffer
2761 size_t old_size;
2762 uint8_t *old_dyn;
2763 size_t new_size;
2764 uint8_t *new_dyn;
2766 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2767 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2769 new_size = old_size + pad_size;
2770 new_dyn = talloc_zero_array(req,
2771 uint8_t, new_size);
2772 if (new_dyn == NULL) {
2773 return smbd_smb2_request_error(req,
2774 NT_STATUS_NO_MEMORY);
2777 memcpy(new_dyn, old_dyn, old_size);
2778 memset(new_dyn + old_size, 0, pad_size);
2780 outdyn_v->iov_base = (void *)new_dyn;
2781 outdyn_v->iov_len = new_size;
2783 next_command_ofs += pad_size;
2786 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
2787 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2788 } else {
2789 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2791 return smbd_smb2_request_reply(req);
2794 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2795 NTSTATUS status,
2796 DATA_BLOB *info,
2797 const char *location)
2799 struct smbXsrv_connection *xconn = req->xconn;
2800 DATA_BLOB body;
2801 DATA_BLOB _dyn;
2802 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2803 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2805 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
2806 "at %s\n", req->current_idx, nt_errstr(status),
2807 info ? " +info" : "", location);
2809 if (unread_bytes) {
2810 /* Recvfile error. Drain incoming socket. */
2811 size_t ret;
2813 errno = 0;
2814 ret = drain_socket(xconn->transport.sock, unread_bytes);
2815 if (ret != unread_bytes) {
2816 NTSTATUS error;
2818 if (errno == 0) {
2819 error = NT_STATUS_IO_DEVICE_ERROR;
2820 } else {
2821 error = map_nt_error_from_unix_common(errno);
2824 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2825 "ret[%u] errno[%d] => %s\n",
2826 (unsigned)unread_bytes,
2827 (unsigned)ret, errno, nt_errstr(error)));
2828 return error;
2832 body.data = outhdr + SMB2_HDR_BODY;
2833 body.length = 8;
2834 SSVAL(body.data, 0, 9);
2836 if (info) {
2837 SIVAL(body.data, 0x04, info->length);
2838 } else {
2839 /* Allocated size of req->out.vector[i].iov_base
2840 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2841 * 1 byte without having to do an alloc.
2843 info = &_dyn;
2844 info->data = ((uint8_t *)outhdr) +
2845 OUTVEC_ALLOC_SIZE - 1;
2846 info->length = 1;
2847 SCVAL(info->data, 0, 0);
2851 * Note: Even if there is an error, continue to process the request.
2852 * per MS-SMB2.
2855 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2859 struct smbd_smb2_send_break_state {
2860 struct smbd_smb2_send_queue queue_entry;
2861 uint8_t nbt_hdr[NBT_HDR_SIZE];
2862 uint8_t tf[SMB2_TF_HDR_SIZE];
2863 uint8_t hdr[SMB2_HDR_BODY];
2864 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2865 uint8_t body[1];
2868 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2869 struct smbXsrv_session *session,
2870 struct smbXsrv_tcon *tcon,
2871 const uint8_t *body,
2872 size_t body_len)
2874 struct smbd_smb2_send_break_state *state;
2875 bool do_encryption = false;
2876 uint64_t session_wire_id = 0;
2877 uint64_t nonce_high = 0;
2878 uint64_t nonce_low = 0;
2879 NTSTATUS status;
2880 size_t statelen;
2881 bool ok;
2883 if (session != NULL) {
2884 session_wire_id = session->global->session_wire_id;
2885 do_encryption = session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
2886 if (tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
2887 do_encryption = true;
2891 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2892 body_len;
2894 state = talloc_zero_size(xconn, statelen);
2895 if (state == NULL) {
2896 return NT_STATUS_NO_MEMORY;
2898 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2900 if (do_encryption) {
2901 status = smb2_get_new_nonce(session,
2902 &nonce_high,
2903 &nonce_low);
2904 if (!NT_STATUS_IS_OK(status)) {
2905 return status;
2909 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2910 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2911 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2912 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2914 SIVAL(state->hdr, 0, SMB2_MAGIC);
2915 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2916 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2917 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2918 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2919 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2920 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2921 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2922 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2923 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2924 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2925 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2926 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2928 state->vector[0] = (struct iovec) {
2929 .iov_base = state->nbt_hdr,
2930 .iov_len = sizeof(state->nbt_hdr)
2933 if (do_encryption) {
2934 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2935 .iov_base = state->tf,
2936 .iov_len = sizeof(state->tf)
2938 } else {
2939 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2940 .iov_base = NULL,
2941 .iov_len = 0
2945 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2946 .iov_base = state->hdr,
2947 .iov_len = sizeof(state->hdr)
2950 memcpy(state->body, body, body_len);
2952 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2953 .iov_base = state->body,
2954 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2958 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2961 ok = smb2_setup_nbt_length(state->vector,
2962 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2963 if (!ok) {
2964 return NT_STATUS_INVALID_PARAMETER_MIX;
2967 if (do_encryption) {
2968 DATA_BLOB encryption_key = session->global->encryption_key;
2970 status = smb2_signing_encrypt_pdu(encryption_key,
2971 xconn->smb2.server.cipher,
2972 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2973 SMBD_SMB2_NUM_IOV_PER_REQ);
2974 if (!NT_STATUS_IS_OK(status)) {
2975 return status;
2979 state->queue_entry.mem_ctx = state;
2980 state->queue_entry.vector = state->vector;
2981 state->queue_entry.count = ARRAY_SIZE(state->vector);
2982 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2983 xconn->smb2.send_queue_len++;
2985 status = smbd_smb2_flush_send_queue(xconn);
2986 if (!NT_STATUS_IS_OK(status)) {
2987 return status;
2990 return NT_STATUS_OK;
2993 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2994 struct smbXsrv_session *session,
2995 struct smbXsrv_tcon *tcon,
2996 struct smbXsrv_open *op,
2997 uint8_t oplock_level)
2999 uint8_t body[0x18];
3001 SSVAL(body, 0x00, sizeof(body));
3002 SCVAL(body, 0x02, oplock_level);
3003 SCVAL(body, 0x03, 0); /* reserved */
3004 SIVAL(body, 0x04, 0); /* reserved */
3005 SBVAL(body, 0x08, op->global->open_persistent_id);
3006 SBVAL(body, 0x10, op->global->open_volatile_id);
3008 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3011 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3012 uint16_t new_epoch,
3013 uint32_t lease_flags,
3014 struct smb2_lease_key *lease_key,
3015 uint32_t current_lease_state,
3016 uint32_t new_lease_state)
3018 uint8_t body[0x2c];
3020 SSVAL(body, 0x00, sizeof(body));
3021 SSVAL(body, 0x02, new_epoch);
3022 SIVAL(body, 0x04, lease_flags);
3023 SBVAL(body, 0x08, lease_key->data[0]);
3024 SBVAL(body, 0x10, lease_key->data[1]);
3025 SIVAL(body, 0x18, current_lease_state);
3026 SIVAL(body, 0x1c, new_lease_state);
3027 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3028 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3029 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3031 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3034 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3036 NTSTATUS status;
3037 uint32_t flags;
3038 uint64_t file_id_persistent;
3039 uint64_t file_id_volatile;
3040 struct smbXsrv_open *op = NULL;
3041 struct files_struct *fsp = NULL;
3042 const uint8_t *body = NULL;
3045 * This is only called with a pktbuf
3046 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3047 * bytes
3050 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3051 /* Transform header. Cannot recvfile. */
3052 return false;
3054 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3055 /* Not SMB2. Normal error path will cope. */
3056 return false;
3058 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3059 /* Not SMB2. Normal error path will cope. */
3060 return false;
3062 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3063 /* Needs to be a WRITE. */
3064 return false;
3066 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3067 /* Chained. Cannot recvfile. */
3068 return false;
3070 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3071 if (flags & SMB2_HDR_FLAG_CHAINED) {
3072 /* Chained. Cannot recvfile. */
3073 return false;
3075 if (flags & SMB2_HDR_FLAG_SIGNED) {
3076 /* Signed. Cannot recvfile. */
3077 return false;
3080 body = &state->pktbuf[SMB2_HDR_BODY];
3082 file_id_persistent = BVAL(body, 0x10);
3083 file_id_volatile = BVAL(body, 0x18);
3085 status = smb2srv_open_lookup(state->req->xconn,
3086 file_id_persistent,
3087 file_id_volatile,
3088 0, /* now */
3089 &op);
3090 if (!NT_STATUS_IS_OK(status)) {
3091 return false;
3094 fsp = op->compat;
3095 if (fsp == NULL) {
3096 return false;
3098 if (fsp->conn == NULL) {
3099 return false;
3102 if (IS_IPC(fsp->conn)) {
3103 return false;
3105 if (IS_PRINT(fsp->conn)) {
3106 return false;
3109 DEBUG(10,("Doing recvfile write len = %u\n",
3110 (unsigned int)(state->pktfull - state->pktlen)));
3112 return true;
3115 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3117 struct smbd_server_connection *sconn = xconn->client->sconn;
3118 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3119 size_t max_send_queue_len;
3120 size_t cur_send_queue_len;
3122 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3124 * we're not supposed to do any io
3126 return NT_STATUS_OK;
3129 if (state->req != NULL) {
3131 * if there is already a tstream_readv_pdu
3132 * pending, we are done.
3134 return NT_STATUS_OK;
3137 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3138 cur_send_queue_len = xconn->smb2.send_queue_len;
3140 if (cur_send_queue_len > max_send_queue_len) {
3142 * if we have a lot of requests to send,
3143 * we wait until they are on the wire until we
3144 * ask for the next request.
3146 return NT_STATUS_OK;
3149 /* ask for the next request */
3150 ZERO_STRUCTP(state);
3151 state->req = smbd_smb2_request_allocate(xconn);
3152 if (state->req == NULL) {
3153 return NT_STATUS_NO_MEMORY;
3155 state->req->sconn = sconn;
3156 state->req->xconn = xconn;
3157 state->min_recv_size = lp_min_receive_file_size();
3159 TEVENT_FD_READABLE(xconn->transport.fde);
3161 return NT_STATUS_OK;
3164 void smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
3165 uint64_t expected_seq_low,
3166 const uint8_t *inpdu, size_t size)
3168 struct smbd_server_connection *sconn = xconn->client->sconn;
3169 NTSTATUS status;
3170 struct smbd_smb2_request *req = NULL;
3172 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3173 (unsigned int)size));
3175 status = smbd_initialize_smb2(xconn, expected_seq_low);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 smbd_server_connection_terminate(xconn, nt_errstr(status));
3178 return;
3181 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 smbd_server_connection_terminate(xconn, nt_errstr(status));
3184 return;
3187 status = smbd_smb2_request_validate(req);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 smbd_server_connection_terminate(xconn, nt_errstr(status));
3190 return;
3193 status = smbd_smb2_request_setup_out(req);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 smbd_server_connection_terminate(xconn, nt_errstr(status));
3196 return;
3199 #ifdef WITH_PROFILE
3201 * this was already counted at the SMB1 layer =>
3202 * smbd_smb2_request_dispatch() should not count it twice.
3204 if (profile_p->values.request_stats.count > 0) {
3205 profile_p->values.request_stats.count--;
3207 #endif
3208 status = smbd_smb2_request_dispatch(req);
3209 if (!NT_STATUS_IS_OK(status)) {
3210 smbd_server_connection_terminate(xconn, nt_errstr(status));
3211 return;
3214 status = smbd_smb2_request_next_incoming(xconn);
3215 if (!NT_STATUS_IS_OK(status)) {
3216 smbd_server_connection_terminate(xconn, nt_errstr(status));
3217 return;
3220 sconn->num_requests++;
3223 static int socket_error_from_errno(int ret,
3224 int sys_errno,
3225 bool *retry)
3227 *retry = false;
3229 if (ret >= 0) {
3230 return 0;
3233 if (ret != -1) {
3234 return EIO;
3237 if (sys_errno == 0) {
3238 return EIO;
3241 if (sys_errno == EINTR) {
3242 *retry = true;
3243 return sys_errno;
3246 if (sys_errno == EINPROGRESS) {
3247 *retry = true;
3248 return sys_errno;
3251 if (sys_errno == EAGAIN) {
3252 *retry = true;
3253 return sys_errno;
3256 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3257 if (sys_errno == ENOMEM) {
3258 *retry = true;
3259 return sys_errno;
3262 #ifdef EWOULDBLOCK
3263 #if EWOULDBLOCK != EAGAIN
3264 if (sys_errno == EWOULDBLOCK) {
3265 *retry = true;
3266 return sys_errno;
3268 #endif
3269 #endif
3271 return sys_errno;
3274 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3276 int ret;
3277 int err;
3278 bool retry;
3280 if (xconn->smb2.send_queue == NULL) {
3281 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3282 return NT_STATUS_OK;
3285 while (xconn->smb2.send_queue != NULL) {
3286 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3287 bool ok;
3289 if (e->sendfile_header != NULL) {
3290 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3291 size_t size = 0;
3292 size_t i = 0;
3293 uint8_t *buf;
3295 for (i=0; i < e->count; i++) {
3296 size += e->vector[i].iov_len;
3299 if (size <= e->sendfile_header->length) {
3300 buf = e->sendfile_header->data;
3301 } else {
3302 buf = talloc_array(e->mem_ctx, uint8_t, size);
3303 if (buf == NULL) {
3304 return NT_STATUS_NO_MEMORY;
3308 size = 0;
3309 for (i=0; i < e->count; i++) {
3310 memcpy(buf+size,
3311 e->vector[i].iov_base,
3312 e->vector[i].iov_len);
3313 size += e->vector[i].iov_len;
3316 e->sendfile_header->data = buf;
3317 e->sendfile_header->length = size;
3318 e->sendfile_status = &status;
3319 e->count = 0;
3321 xconn->smb2.send_queue_len--;
3322 DLIST_REMOVE(xconn->smb2.send_queue, e);
3324 * This triggers the sendfile path via
3325 * the destructor.
3327 talloc_free(e->mem_ctx);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 return status;
3332 continue;
3335 ret = writev(xconn->transport.sock, e->vector, e->count);
3336 if (ret == 0) {
3337 /* propagate end of file */
3338 return NT_STATUS_INTERNAL_ERROR;
3340 err = socket_error_from_errno(ret, errno, &retry);
3341 if (retry) {
3342 /* retry later */
3343 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3344 return NT_STATUS_OK;
3346 if (err != 0) {
3347 return map_nt_error_from_unix_common(err);
3350 ok = iov_advance(&e->vector, &e->count, ret);
3351 if (!ok) {
3352 return NT_STATUS_INTERNAL_ERROR;
3355 if (e->count > 0) {
3356 /* we have more to write */
3357 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3358 return NT_STATUS_OK;
3361 xconn->smb2.send_queue_len--;
3362 DLIST_REMOVE(xconn->smb2.send_queue, e);
3363 talloc_free(e->mem_ctx);
3366 return NT_STATUS_OK;
3369 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3370 uint16_t fde_flags)
3372 struct smbd_server_connection *sconn = xconn->client->sconn;
3373 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3374 struct smbd_smb2_request *req = NULL;
3375 size_t min_recvfile_size = UINT32_MAX;
3376 int ret;
3377 int err;
3378 bool retry;
3379 NTSTATUS status;
3380 NTTIME now;
3382 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3384 * we're not supposed to do any io
3386 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3387 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3388 return NT_STATUS_OK;
3391 if (fde_flags & TEVENT_FD_WRITE) {
3392 status = smbd_smb2_flush_send_queue(xconn);
3393 if (!NT_STATUS_IS_OK(status)) {
3394 return status;
3398 if (!(fde_flags & TEVENT_FD_READ)) {
3399 return NT_STATUS_OK;
3402 if (state->req == NULL) {
3403 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3404 return NT_STATUS_OK;
3407 again:
3408 if (!state->hdr.done) {
3409 state->hdr.done = true;
3411 state->vector.iov_base = (void *)state->hdr.nbt;
3412 state->vector.iov_len = NBT_HDR_SIZE;
3415 ret = readv(xconn->transport.sock, &state->vector, 1);
3416 if (ret == 0) {
3417 /* propagate end of file */
3418 return NT_STATUS_END_OF_FILE;
3420 err = socket_error_from_errno(ret, errno, &retry);
3421 if (retry) {
3422 /* retry later */
3423 TEVENT_FD_READABLE(xconn->transport.fde);
3424 return NT_STATUS_OK;
3426 if (err != 0) {
3427 return map_nt_error_from_unix_common(err);
3430 if (ret < state->vector.iov_len) {
3431 uint8_t *base;
3432 base = (uint8_t *)state->vector.iov_base;
3433 base += ret;
3434 state->vector.iov_base = (void *)base;
3435 state->vector.iov_len -= ret;
3436 /* we have more to read */
3437 TEVENT_FD_READABLE(xconn->transport.fde);
3438 return NT_STATUS_OK;
3441 if (state->pktlen > 0) {
3442 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3444 * Not a possible receivefile write.
3445 * Read the rest of the data.
3447 state->doing_receivefile = false;
3449 state->pktbuf = talloc_realloc(state->req,
3450 state->pktbuf,
3451 uint8_t,
3452 state->pktfull);
3453 if (state->pktbuf == NULL) {
3454 return NT_STATUS_NO_MEMORY;
3457 state->vector.iov_base = (void *)(state->pktbuf +
3458 state->pktlen);
3459 state->vector.iov_len = (state->pktfull -
3460 state->pktlen);
3462 state->pktlen = state->pktfull;
3463 goto again;
3467 * Either this is a receivefile write so we've
3468 * done a short read, or if not we have all the data.
3470 goto got_full;
3474 * Now we analyze the NBT header
3476 if (state->hdr.nbt[0] != 0x00) {
3477 state->min_recv_size = 0;
3479 state->pktfull = smb2_len(state->hdr.nbt);
3480 if (state->pktfull == 0) {
3481 goto got_full;
3484 if (state->min_recv_size != 0) {
3485 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3486 min_recvfile_size += state->min_recv_size;
3489 if (state->pktfull > min_recvfile_size) {
3491 * Might be a receivefile write. Read the SMB2 HEADER +
3492 * SMB2_WRITE header first. Set 'doing_receivefile'
3493 * as we're *attempting* receivefile write. If this
3494 * turns out not to be a SMB2_WRITE request or otherwise
3495 * not suitable then we'll just read the rest of the data
3496 * the next time this function is called.
3498 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3499 state->doing_receivefile = true;
3500 } else {
3501 state->pktlen = state->pktfull;
3504 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3505 if (state->pktbuf == NULL) {
3506 return NT_STATUS_NO_MEMORY;
3509 state->vector.iov_base = (void *)state->pktbuf;
3510 state->vector.iov_len = state->pktlen;
3512 goto again;
3514 got_full:
3516 if (state->hdr.nbt[0] != 0x00) {
3517 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3518 state->hdr.nbt[0]));
3520 req = state->req;
3521 ZERO_STRUCTP(state);
3522 state->req = req;
3523 state->min_recv_size = lp_min_receive_file_size();
3524 req = NULL;
3525 goto again;
3528 req = state->req;
3529 state->req = NULL;
3531 req->request_time = timeval_current();
3532 now = timeval_to_nttime(&req->request_time);
3534 status = smbd_smb2_inbuf_parse_compound(xconn,
3535 now,
3536 state->pktbuf,
3537 state->pktlen,
3538 req,
3539 &req->in.vector,
3540 &req->in.vector_count);
3541 if (!NT_STATUS_IS_OK(status)) {
3542 return status;
3545 if (state->doing_receivefile) {
3546 req->smb1req = talloc_zero(req, struct smb_request);
3547 if (req->smb1req == NULL) {
3548 return NT_STATUS_NO_MEMORY;
3550 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3553 ZERO_STRUCTP(state);
3555 req->current_idx = 1;
3557 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3558 req->current_idx, req->in.vector_count));
3560 status = smbd_smb2_request_validate(req);
3561 if (!NT_STATUS_IS_OK(status)) {
3562 return status;
3565 status = smbd_smb2_request_setup_out(req);
3566 if (!NT_STATUS_IS_OK(status)) {
3567 return status;
3570 status = smbd_smb2_request_dispatch(req);
3571 if (!NT_STATUS_IS_OK(status)) {
3572 return status;
3575 sconn->num_requests++;
3577 /* The timeout_processing function isn't run nearly
3578 often enough to implement 'max log size' without
3579 overrunning the size of the file by many megabytes.
3580 This is especially true if we are running at debug
3581 level 10. Checking every 50 SMB2s is a nice
3582 tradeoff of performance vs log file size overrun. */
3584 if ((sconn->num_requests % 50) == 0 &&
3585 need_to_check_log_size()) {
3586 change_to_root_user();
3587 check_log_size();
3590 status = smbd_smb2_request_next_incoming(xconn);
3591 if (!NT_STATUS_IS_OK(status)) {
3592 return status;
3595 return NT_STATUS_OK;
3598 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3599 struct tevent_fd *fde,
3600 uint16_t flags,
3601 void *private_data)
3603 struct smbXsrv_connection *xconn =
3604 talloc_get_type_abort(private_data,
3605 struct smbXsrv_connection);
3606 NTSTATUS status;
3608 status = smbd_smb2_io_handler(xconn, flags);
3609 if (!NT_STATUS_IS_OK(status)) {
3610 smbd_server_connection_terminate(xconn, nt_errstr(status));
3611 return;