s3:smb2_server: use req->xconn in smbd_smb2_request_check_session()
[Samba.git] / source3 / smbd / smb2_server.c
blob04f1e4ee7838d7e806a53ac878acc6bc3808673b
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 "auth.h"
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
35 uint16_t flags,
36 void *private_data);
37 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
39 static const struct smbd_smb2_dispatch_table {
40 uint16_t opcode;
41 const char *name;
42 bool need_session;
43 bool need_tcon;
44 bool as_root;
45 uint16_t fileid_ofs;
46 bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
50 _OP(SMB2_OP_NEGPROT),
51 .as_root = true,
52 },{
53 _OP(SMB2_OP_SESSSETUP),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_LOGOFF),
57 .need_session = true,
58 .as_root = true,
59 },{
60 _OP(SMB2_OP_TCON),
61 .need_session = true,
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
69 .as_root = true,
70 },{
71 _OP(SMB2_OP_TDIS),
72 .need_session = true,
73 .need_tcon = true,
74 .as_root = true,
75 },{
76 _OP(SMB2_OP_CREATE),
77 .need_session = true,
78 .need_tcon = true,
79 },{
80 _OP(SMB2_OP_CLOSE),
81 .need_session = true,
82 .need_tcon = true,
83 .fileid_ofs = 0x08,
84 },{
85 _OP(SMB2_OP_FLUSH),
86 .need_session = true,
87 .need_tcon = true,
88 .fileid_ofs = 0x08,
89 },{
90 _OP(SMB2_OP_READ),
91 .need_session = true,
92 .need_tcon = true,
93 .fileid_ofs = 0x10,
94 },{
95 _OP(SMB2_OP_WRITE),
96 .need_session = true,
97 .need_tcon = true,
98 .fileid_ofs = 0x10,
99 },{
100 _OP(SMB2_OP_LOCK),
101 .need_session = true,
102 .need_tcon = true,
103 .fileid_ofs = 0x08,
105 _OP(SMB2_OP_IOCTL),
106 .need_session = true,
107 .need_tcon = true,
108 .fileid_ofs = 0x08,
109 .allow_invalid_fileid = true,
111 _OP(SMB2_OP_CANCEL),
112 .as_root = true,
114 _OP(SMB2_OP_KEEPALIVE),
115 .as_root = true,
117 _OP(SMB2_OP_FIND),
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x08,
122 _OP(SMB2_OP_NOTIFY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_GETINFO),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x18,
132 _OP(SMB2_OP_SETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x10,
137 _OP(SMB2_OP_BREAK),
138 .need_session = true,
139 .need_tcon = true,
141 * we do not set
142 * .fileid_ofs here
143 * as LEASE breaks does not
144 * have a file id
149 const char *smb2_opcode_name(uint16_t opcode)
151 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table[opcode].name;
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 const struct smbd_smb2_dispatch_table *ret = NULL;
161 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
162 return NULL;
165 ret = &smbd_smb2_table[opcode];
167 SMB_ASSERT(ret->opcode == opcode);
169 return ret;
172 static void print_req_vectors(const struct smbd_smb2_request *req)
174 int i;
176 for (i = 0; i < req->in.vector_count; i++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
178 (unsigned int)i,
179 (unsigned int)req->in.vector[i].iov_len);
181 for (i = 0; i < req->out.vector_count; i++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
183 (unsigned int)i,
184 (unsigned int)req->out.vector[i].iov_len);
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 if (size < (4 + SMB2_HDR_BODY)) {
191 return false;
194 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
195 return false;
198 return true;
201 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
203 TALLOC_FREE(xconn->transport.fde);
205 xconn->smb2.credits.seq_low = 0;
206 xconn->smb2.credits.seq_range = 1;
207 xconn->smb2.credits.granted = 1;
208 xconn->smb2.credits.max = lp_smb2_max_credits();
209 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
210 xconn->smb2.credits.max);
211 if (xconn->smb2.credits.bitmap == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
216 xconn,
217 xconn->transport.sock,
218 TEVENT_FD_READ,
219 smbd_smb2_connection_handler,
220 xconn);
221 if (xconn->transport.fde == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* Ensure child is set to non-blocking mode */
226 set_blocking(xconn->transport.sock, false);
227 return NT_STATUS_OK;
230 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
231 #define _smb2_setlen(_buf,len) do { \
232 uint8_t *buf = (uint8_t *)_buf; \
233 buf[0] = 0; \
234 buf[1] = ((len)&0xFF0000)>>16; \
235 buf[2] = ((len)&0xFF00)>>8; \
236 buf[3] = (len)&0xFF; \
237 } while (0)
239 static void smb2_setup_nbt_length(struct iovec *vector, int count)
241 size_t len = 0;
242 int i;
244 for (i=1; i < count; i++) {
245 len += vector[i].iov_len;
248 _smb2_setlen(vector[0].iov_base, len);
251 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
253 if (req->first_key.length > 0) {
254 data_blob_clear_free(&req->first_key);
256 if (req->last_key.length > 0) {
257 data_blob_clear_free(&req->last_key);
259 return 0;
262 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
264 TALLOC_CTX *mem_pool;
265 struct smbd_smb2_request *req;
267 #if 0
268 /* Enable this to find subtle valgrind errors. */
269 mem_pool = talloc_init("smbd_smb2_request_allocate");
270 #else
271 mem_pool = talloc_tos();
272 #endif
273 if (mem_pool == NULL) {
274 return NULL;
277 req = talloc_zero(mem_pool, struct smbd_smb2_request);
278 if (req == NULL) {
279 talloc_free(mem_pool);
280 return NULL;
282 talloc_reparent(mem_pool, mem_ctx, req);
283 #if 0
284 TALLOC_FREE(mem_pool);
285 #endif
287 req->last_session_id = UINT64_MAX;
288 req->last_tid = UINT32_MAX;
290 talloc_set_destructor(req, smbd_smb2_request_destructor);
292 return req;
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
296 NTTIME now,
297 uint8_t *buf,
298 size_t buflen,
299 struct smbd_smb2_request *req,
300 struct iovec **piov,
301 int *pnum_iov)
303 TALLOC_CTX *mem_ctx = req;
304 struct iovec *iov;
305 int num_iov = 1;
306 size_t taken = 0;
307 uint8_t *first_hdr = buf;
308 size_t verified_buflen = 0;
309 uint8_t *tf = NULL;
310 size_t tf_len = 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov = req->in._vector;
317 while (taken < buflen) {
318 size_t len = buflen - taken;
319 uint8_t *hdr = first_hdr + taken;
320 struct iovec *cur;
321 size_t full_size;
322 size_t next_command_ofs;
323 uint16_t body_size;
324 uint8_t *body = NULL;
325 uint32_t dyn_size;
326 uint8_t *dyn = NULL;
327 struct iovec *iov_alloc = NULL;
329 if (iov != req->in._vector) {
330 iov_alloc = iov;
333 if (verified_buflen > taken) {
334 len = verified_buflen - taken;
335 } else {
336 tf = NULL;
337 tf_len = 0;
340 if (len < 4) {
341 DEBUG(10, ("%d bytes left, expected at least %d\n",
342 (int)len, 4));
343 goto inval;
345 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
346 struct smbXsrv_session *s = NULL;
347 uint64_t uid;
348 struct iovec tf_iov[2];
349 NTSTATUS status;
350 size_t enc_len;
352 if (xconn->protocol < PROTOCOL_SMB2_24) {
353 DEBUG(10, ("Got SMB2_TRANSFORM header, "
354 "but dialect[0x%04X] is used\n",
355 xconn->smb2.server.dialect));
356 goto inval;
359 if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but not negotiated "
362 "client[0x%08X] server[0x%08X]\n",
363 xconn->smb2.client.capabilities,
364 xconn->smb2.server.capabilities));
365 goto inval;
368 if (len < SMB2_TF_HDR_SIZE) {
369 DEBUG(1, ("%d bytes left, expected at least %d\n",
370 (int)len, SMB2_TF_HDR_SIZE));
371 goto inval;
373 tf = hdr;
374 tf_len = SMB2_TF_HDR_SIZE;
375 taken += tf_len;
377 hdr = first_hdr + taken;
378 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
379 uid = BVAL(tf, SMB2_TF_SESSION_ID);
381 if (len < SMB2_TF_HDR_SIZE + enc_len) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)len,
384 (int)(SMB2_TF_HDR_SIZE + enc_len)));
385 goto inval;
388 status = smb2srv_session_lookup(xconn, uid, now, &s);
389 if (s == NULL) {
390 DEBUG(1, ("invalid session[%llu] in "
391 "SMB2_TRANSFORM header\n",
392 (unsigned long long)uid));
393 TALLOC_FREE(iov_alloc);
394 return NT_STATUS_USER_SESSION_DELETED;
397 tf_iov[0].iov_base = (void *)tf;
398 tf_iov[0].iov_len = tf_len;
399 tf_iov[1].iov_base = (void *)hdr;
400 tf_iov[1].iov_len = enc_len;
402 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
403 xconn->protocol,
404 tf_iov, 2);
405 if (!NT_STATUS_IS_OK(status)) {
406 TALLOC_FREE(iov_alloc);
407 return status;
410 verified_buflen = taken + enc_len;
411 len = enc_len;
415 * We need the header plus the body length field
418 if (len < SMB2_HDR_BODY + 2) {
419 DEBUG(10, ("%d bytes left, expected at least %d\n",
420 (int)len, SMB2_HDR_BODY));
421 goto inval;
423 if (IVAL(hdr, 0) != SMB2_MAGIC) {
424 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
425 IVAL(hdr, 0)));
426 goto inval;
428 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
429 DEBUG(10, ("Got HDR len %d, expected %d\n",
430 SVAL(hdr, 4), SMB2_HDR_BODY));
431 goto inval;
434 full_size = len;
435 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
436 body_size = SVAL(hdr, SMB2_HDR_BODY);
438 if (next_command_ofs != 0) {
439 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
440 goto inval;
442 if (next_command_ofs > full_size) {
443 goto inval;
445 full_size = next_command_ofs;
447 if (body_size < 2) {
448 goto inval;
450 body_size &= 0xfffe;
452 if (body_size > (full_size - SMB2_HDR_BODY)) {
454 * let the caller handle the error
456 body_size = full_size - SMB2_HDR_BODY;
458 body = hdr + SMB2_HDR_BODY;
459 dyn = body + body_size;
460 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
462 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
463 struct iovec *iov_tmp = NULL;
465 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
466 struct iovec,
467 num_iov +
468 SMBD_SMB2_NUM_IOV_PER_REQ);
469 if (iov_tmp == NULL) {
470 TALLOC_FREE(iov_alloc);
471 return NT_STATUS_NO_MEMORY;
474 if (iov_alloc == NULL) {
475 memcpy(iov_tmp,
476 req->in._vector,
477 sizeof(req->in._vector));
480 iov = iov_tmp;
482 cur = &iov[num_iov];
483 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
485 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
486 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
487 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
488 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
489 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
490 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
491 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
492 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
494 taken += full_size;
497 *piov = iov;
498 *pnum_iov = num_iov;
499 return NT_STATUS_OK;
501 inval:
502 if (iov != req->in._vector) {
503 TALLOC_FREE(iov);
505 return NT_STATUS_INVALID_PARAMETER;
508 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
509 uint8_t *inbuf, size_t size,
510 struct smbd_smb2_request **_req)
512 struct smbd_server_connection *sconn = xconn->sconn;
513 struct smbd_smb2_request *req;
514 uint32_t protocol_version;
515 const uint8_t *inhdr = NULL;
516 uint16_t cmd;
517 uint32_t next_command_ofs;
518 NTSTATUS status;
519 NTTIME now;
521 if (size < (4 + SMB2_HDR_BODY + 2)) {
522 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
523 return NT_STATUS_INVALID_PARAMETER;
526 inhdr = inbuf + 4;
528 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
529 if (protocol_version != SMB2_MAGIC) {
530 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
531 protocol_version));
532 return NT_STATUS_INVALID_PARAMETER;
535 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
536 if (cmd != SMB2_OP_NEGPROT) {
537 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
538 cmd));
539 return NT_STATUS_INVALID_PARAMETER;
542 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
543 if (next_command_ofs != 0) {
544 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
545 next_command_ofs));
546 return NT_STATUS_INVALID_PARAMETER;
549 req = smbd_smb2_request_allocate(xconn);
550 if (req == NULL) {
551 return NT_STATUS_NO_MEMORY;
553 req->sconn = sconn;
554 req->xconn = xconn;
556 talloc_steal(req, inbuf);
558 req->request_time = timeval_current();
559 now = timeval_to_nttime(&req->request_time);
561 status = smbd_smb2_inbuf_parse_compound(xconn,
562 now,
563 inbuf + NBT_HDR_SIZE,
564 size - NBT_HDR_SIZE,
565 req, &req->in.vector,
566 &req->in.vector_count);
567 if (!NT_STATUS_IS_OK(status)) {
568 TALLOC_FREE(req);
569 return status;
572 req->current_idx = 1;
574 *_req = req;
575 return NT_STATUS_OK;
578 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
579 uint64_t message_id, uint64_t seq_id)
581 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
582 unsigned int offset;
583 uint64_t seq_tmp;
585 seq_tmp = xconn->smb2.credits.seq_low;
586 if (seq_id < seq_tmp) {
587 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
588 "%llu (sequence id %llu) "
589 "(granted = %u, low = %llu, range = %u)\n",
590 (unsigned long long)message_id,
591 (unsigned long long)seq_id,
592 (unsigned int)xconn->smb2.credits.granted,
593 (unsigned long long)xconn->smb2.credits.seq_low,
594 (unsigned int)xconn->smb2.credits.seq_range));
595 return false;
598 seq_tmp += xconn->smb2.credits.seq_range;
599 if (seq_id >= seq_tmp) {
600 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
601 "%llu (sequence id %llu) "
602 "(granted = %u, low = %llu, range = %u)\n",
603 (unsigned long long)message_id,
604 (unsigned long long)seq_id,
605 (unsigned int)xconn->smb2.credits.granted,
606 (unsigned long long)xconn->smb2.credits.seq_low,
607 (unsigned int)xconn->smb2.credits.seq_range));
608 return false;
611 offset = seq_id % xconn->smb2.credits.max;
613 if (bitmap_query(credits_bm, offset)) {
614 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
615 "%llu (sequence id %llu) "
616 "(granted = %u, low = %llu, range = %u) "
617 "(bm offset %u)\n",
618 (unsigned long long)message_id,
619 (unsigned long long)seq_id,
620 (unsigned int)xconn->smb2.credits.granted,
621 (unsigned long long)xconn->smb2.credits.seq_low,
622 (unsigned int)xconn->smb2.credits.seq_range,
623 offset));
624 return false;
627 /* Mark the message_ids as seen in the bitmap. */
628 bitmap_set(credits_bm, offset);
630 if (seq_id != xconn->smb2.credits.seq_low) {
631 return true;
635 * Move the window forward by all the message_id's
636 * already seen.
638 while (bitmap_query(credits_bm, offset)) {
639 DEBUG(10,("smb2_validate_sequence_number: clearing "
640 "id %llu (position %u) from bitmap\n",
641 (unsigned long long)(xconn->smb2.credits.seq_low),
642 offset));
643 bitmap_clear(credits_bm, offset);
645 xconn->smb2.credits.seq_low += 1;
646 xconn->smb2.credits.seq_range -= 1;
647 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
650 return true;
653 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
654 const uint8_t *inhdr)
656 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
657 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
658 uint16_t credit_charge = 1;
659 uint64_t i;
661 if (opcode == SMB2_OP_CANCEL) {
662 /* SMB2_CANCEL requests by definition resend messageids. */
663 return true;
666 if (xconn->smb2.credits.multicredit) {
667 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
668 credit_charge = MAX(credit_charge, 1);
671 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
672 "credits_granted %llu, "
673 "seqnum low/range: %llu/%llu\n",
674 (unsigned long long) message_id,
675 (unsigned long long) credit_charge,
676 (unsigned long long) xconn->smb2.credits.granted,
677 (unsigned long long) xconn->smb2.credits.seq_low,
678 (unsigned long long) xconn->smb2.credits.seq_range));
680 if (xconn->smb2.credits.granted < credit_charge) {
681 DEBUG(0, ("smb2_validate_message_id: client used more "
682 "credits than granted, mid %llu, charge %llu, "
683 "credits_granted %llu, "
684 "seqnum low/range: %llu/%llu\n",
685 (unsigned long long) message_id,
686 (unsigned long long) credit_charge,
687 (unsigned long long) xconn->smb2.credits.granted,
688 (unsigned long long) xconn->smb2.credits.seq_low,
689 (unsigned long long) xconn->smb2.credits.seq_range));
690 return false;
694 * now check the message ids
696 * for multi-credit requests we need to check all current mid plus
697 * the implicit mids caused by the credit charge
698 * e.g. current mid = 15, charge 5 => mark 15-19 as used
701 for (i = 0; i <= (credit_charge-1); i++) {
702 uint64_t id = message_id + i;
703 bool ok;
705 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
706 (unsigned long long)message_id,
707 credit_charge,
708 (unsigned long long)id));
710 ok = smb2_validate_sequence_number(xconn, message_id, id);
711 if (!ok) {
712 return false;
716 /* substract used credits */
717 xconn->smb2.credits.granted -= credit_charge;
719 return true;
722 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
724 int count;
725 int idx;
727 count = req->in.vector_count;
729 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
730 /* It's not a SMB2 request */
731 return NT_STATUS_INVALID_PARAMETER;
734 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
735 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
736 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
737 const uint8_t *inhdr = NULL;
739 if (hdr->iov_len != SMB2_HDR_BODY) {
740 return NT_STATUS_INVALID_PARAMETER;
743 if (body->iov_len < 2) {
744 return NT_STATUS_INVALID_PARAMETER;
747 inhdr = (const uint8_t *)hdr->iov_base;
749 /* Check the SMB2 header */
750 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
751 return NT_STATUS_INVALID_PARAMETER;
754 if (!smb2_validate_message_id(req->xconn, inhdr)) {
755 return NT_STATUS_INVALID_PARAMETER;
759 return NT_STATUS_OK;
762 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
763 const struct iovec *in_vector,
764 struct iovec *out_vector)
766 struct smbd_server_connection *sconn = xconn->sconn;
767 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
768 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
769 uint16_t credit_charge = 1;
770 uint16_t credits_requested;
771 uint32_t out_flags;
772 uint16_t cmd;
773 NTSTATUS out_status;
774 uint16_t credits_granted = 0;
775 uint64_t credits_possible;
776 uint16_t current_max_credits;
779 * first we grant only 1/16th of the max range.
781 * Windows also starts with the 1/16th and then grants
782 * more later. I was only able to trigger higher
783 * values, when using a very high credit charge.
785 * TODO: scale up depending on load, free memory
786 * or other stuff.
787 * Maybe also on the relationship between number
788 * of requests and the used sequence number.
789 * Which means we would grant more credits
790 * for client which use multi credit requests.
792 current_max_credits = xconn->smb2.credits.max / 16;
793 current_max_credits = MAX(current_max_credits, 1);
795 if (xconn->smb2.credits.multicredit) {
796 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
797 credit_charge = MAX(credit_charge, 1);
800 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
801 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
802 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
803 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
805 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
807 if (xconn->smb2.credits.max < credit_charge) {
808 smbd_server_connection_terminate(sconn,
809 "client error: credit charge > max credits\n");
810 return;
813 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
815 * In case we already send an async interim
816 * response, we should not grant
817 * credits on the final response.
819 credits_granted = 0;
820 } else if (credits_requested > 0) {
821 uint16_t additional_max = 0;
822 uint16_t additional_credits = credits_requested - 1;
824 switch (cmd) {
825 case SMB2_OP_NEGPROT:
826 break;
827 case SMB2_OP_SESSSETUP:
829 * Windows 2012 RC1 starts to grant
830 * additional credits
831 * with a successful session setup
833 if (NT_STATUS_IS_OK(out_status)) {
834 additional_max = 32;
836 break;
837 default:
839 * We match windows and only grant additional credits
840 * in chunks of 32.
842 additional_max = 32;
843 break;
846 additional_credits = MIN(additional_credits, additional_max);
848 credits_granted = credit_charge + additional_credits;
849 } else if (xconn->smb2.credits.granted == 0) {
851 * Make sure the client has always at least one credit
853 credits_granted = 1;
857 * sequence numbers should not wrap
859 * 1. calculate the possible credits until
860 * the sequence numbers start to wrap on 64-bit.
862 * 2. UINT64_MAX is used for Break Notifications.
864 * 2. truncate the possible credits to the maximum
865 * credits we want to grant to the client in total.
867 * 3. remove the range we'll already granted to the client
868 * this makes sure the client consumes the lowest sequence
869 * number, before we can grant additional credits.
871 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
872 if (credits_possible > 0) {
873 /* remove UINT64_MAX */
874 credits_possible -= 1;
876 credits_possible = MIN(credits_possible, current_max_credits);
877 credits_possible -= xconn->smb2.credits.seq_range;
879 credits_granted = MIN(credits_granted, credits_possible);
881 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
882 xconn->smb2.credits.granted += credits_granted;
883 xconn->smb2.credits.seq_range += credits_granted;
885 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
886 "granted %u, current possible/max %u/%u, "
887 "total granted/max/low/range %u/%u/%llu/%u\n",
888 (unsigned int)credits_requested,
889 (unsigned int)credit_charge,
890 (unsigned int)credits_granted,
891 (unsigned int)credits_possible,
892 (unsigned int)current_max_credits,
893 (unsigned int)xconn->smb2.credits.granted,
894 (unsigned int)xconn->smb2.credits.max,
895 (unsigned long long)xconn->smb2.credits.seq_low,
896 (unsigned int)xconn->smb2.credits.seq_range));
899 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
900 struct smbd_smb2_request *outreq)
902 int count, idx;
903 uint16_t total_credits = 0;
905 count = outreq->out.vector_count;
907 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
908 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
909 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
910 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
912 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
914 /* To match Windows, count up what we
915 just granted. */
916 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
917 /* Set to zero in all but the last reply. */
918 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
919 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
920 } else {
921 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
926 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
928 if (req->current_idx <= 1) {
929 if (size <= sizeof(req->out._body)) {
930 return data_blob_const(req->out._body, size);
934 return data_blob_talloc(req, NULL, size);
937 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
939 struct smbXsrv_connection *xconn = req->xconn;
940 TALLOC_CTX *mem_ctx;
941 struct iovec *vector;
942 int count;
943 int idx;
945 count = req->in.vector_count;
946 if (count <= ARRAY_SIZE(req->out._vector)) {
947 mem_ctx = req;
948 vector = req->out._vector;
949 } else {
950 vector = talloc_zero_array(req, struct iovec, count);
951 if (vector == NULL) {
952 return NT_STATUS_NO_MEMORY;
954 mem_ctx = vector;
957 vector[0].iov_base = req->out.nbt_hdr;
958 vector[0].iov_len = 4;
959 SIVAL(req->out.nbt_hdr, 0, 0);
961 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
962 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
963 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
964 uint8_t *outhdr = NULL;
965 uint8_t *outbody = NULL;
966 uint32_t next_command_ofs = 0;
967 struct iovec *current = &vector[idx];
969 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
970 /* we have a next command -
971 * setup for the error case. */
972 next_command_ofs = SMB2_HDR_BODY + 9;
975 if (idx == 1) {
976 outhdr = req->out._hdr;
977 } else {
978 outhdr = talloc_zero_array(mem_ctx, uint8_t,
979 OUTVEC_ALLOC_SIZE);
980 if (outhdr == NULL) {
981 return NT_STATUS_NO_MEMORY;
985 outbody = outhdr + SMB2_HDR_BODY;
988 * SMBD_SMB2_TF_IOV_OFS might be used later
990 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
991 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
993 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
994 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
996 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
997 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
999 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1000 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1002 /* setup the SMB2 header */
1003 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1004 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1005 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1006 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1007 SIVAL(outhdr, SMB2_HDR_STATUS,
1008 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1009 SSVAL(outhdr, SMB2_HDR_OPCODE,
1010 SVAL(inhdr, SMB2_HDR_OPCODE));
1011 SIVAL(outhdr, SMB2_HDR_FLAGS,
1012 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1013 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1014 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1015 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1016 SIVAL(outhdr, SMB2_HDR_PID,
1017 IVAL(inhdr, SMB2_HDR_PID));
1018 SIVAL(outhdr, SMB2_HDR_TID,
1019 IVAL(inhdr, SMB2_HDR_TID));
1020 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1021 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1022 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1023 inhdr + SMB2_HDR_SIGNATURE, 16);
1025 /* setup error body header */
1026 SSVAL(outbody, 0x00, 0x08 + 1);
1027 SSVAL(outbody, 0x02, 0);
1028 SIVAL(outbody, 0x04, 0);
1031 req->out.vector = vector;
1032 req->out.vector_count = count;
1034 /* setup the length of the NBT packet */
1035 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1037 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1039 return NT_STATUS_OK;
1042 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1043 const char *reason,
1044 const char *location)
1046 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1047 reason, location));
1048 exit_server_cleanly(reason);
1051 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1052 struct iovec *outvec,
1053 const struct iovec *srcvec)
1055 const uint8_t *srctf;
1056 size_t srctf_len;
1057 const uint8_t *srchdr;
1058 size_t srchdr_len;
1059 const uint8_t *srcbody;
1060 size_t srcbody_len;
1061 const uint8_t *expected_srcbody;
1062 const uint8_t *srcdyn;
1063 size_t srcdyn_len;
1064 const uint8_t *expected_srcdyn;
1065 uint8_t *dsttf;
1066 uint8_t *dsthdr;
1067 uint8_t *dstbody;
1068 uint8_t *dstdyn;
1070 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1071 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1072 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1073 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1074 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1075 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1076 expected_srcbody = srchdr + SMB2_HDR_BODY;
1077 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1078 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1079 expected_srcdyn = srcbody + 8;
1081 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1082 return false;
1085 if (srchdr_len != SMB2_HDR_BODY) {
1086 return false;
1089 if (srctf_len == SMB2_TF_HDR_SIZE) {
1090 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1091 if (dsttf == NULL) {
1092 return false;
1094 } else {
1095 dsttf = NULL;
1097 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1098 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1100 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1101 * be allocated with size OUTVEC_ALLOC_SIZE. */
1103 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1104 if (dsthdr == NULL) {
1105 return false;
1107 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1108 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1111 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1112 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1113 * then duplicate this. Else use talloc_memdup().
1116 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1117 dstbody = dsthdr + SMB2_HDR_BODY;
1118 } else {
1119 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1120 if (dstbody == NULL) {
1121 return false;
1124 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1125 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1128 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1129 * pointing to
1130 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1131 * then duplicate this. Else use talloc_memdup().
1134 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1135 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1136 } else if (srcdyn == NULL) {
1137 dstdyn = NULL;
1138 } else {
1139 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1140 if (dstdyn == NULL) {
1141 return false;
1144 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1145 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1147 return true;
1150 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1152 struct smbd_smb2_request *newreq = NULL;
1153 struct iovec *outvec = NULL;
1154 int count = req->out.vector_count;
1155 int i;
1157 newreq = smbd_smb2_request_allocate(req->xconn);
1158 if (!newreq) {
1159 return NULL;
1162 newreq->sconn = req->sconn;
1163 newreq->xconn = req->xconn;
1164 newreq->session = req->session;
1165 newreq->do_encryption = req->do_encryption;
1166 newreq->do_signing = req->do_signing;
1167 newreq->current_idx = req->current_idx;
1169 outvec = talloc_zero_array(newreq, struct iovec, count);
1170 if (!outvec) {
1171 TALLOC_FREE(newreq);
1172 return NULL;
1174 newreq->out.vector = outvec;
1175 newreq->out.vector_count = count;
1177 /* Setup the outvec's identically to req. */
1178 outvec[0].iov_base = newreq->out.nbt_hdr;
1179 outvec[0].iov_len = 4;
1180 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1182 /* Setup the vectors identically to the ones in req. */
1183 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1184 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1185 break;
1189 if (i < count) {
1190 /* Alloc failed. */
1191 TALLOC_FREE(newreq);
1192 return NULL;
1195 smb2_setup_nbt_length(newreq->out.vector,
1196 newreq->out.vector_count);
1198 return newreq;
1201 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1203 struct smbXsrv_connection *xconn = req->xconn;
1204 int first_idx = 1;
1205 struct iovec *firsttf = NULL;
1206 struct iovec *outhdr_v = NULL;
1207 uint8_t *outhdr = NULL;
1208 struct smbd_smb2_request *nreq = NULL;
1209 NTSTATUS status;
1211 /* Create a new smb2 request we'll use
1212 for the interim return. */
1213 nreq = dup_smb2_req(req);
1214 if (!nreq) {
1215 return NT_STATUS_NO_MEMORY;
1218 /* Lose the last X out vectors. They're the
1219 ones we'll be using for the async reply. */
1220 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1222 smb2_setup_nbt_length(nreq->out.vector,
1223 nreq->out.vector_count);
1225 /* Step back to the previous reply. */
1226 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1227 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1228 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1229 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1230 /* And end the chain. */
1231 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1233 /* Calculate outgoing credits */
1234 smb2_calculate_credits(req, nreq);
1236 if (DEBUGLEVEL >= 10) {
1237 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1238 (unsigned int)nreq->current_idx );
1239 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1240 (unsigned int)nreq->out.vector_count );
1241 print_req_vectors(nreq);
1245 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1246 * we need to sign/encrypt here with the last/first key we remembered
1248 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1249 status = smb2_signing_encrypt_pdu(req->first_key,
1250 xconn->protocol,
1251 firsttf,
1252 nreq->out.vector_count - first_idx);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 return status;
1256 } else if (req->last_key.length > 0) {
1257 status = smb2_signing_sign_pdu(req->last_key,
1258 xconn->protocol,
1259 outhdr_v,
1260 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 return status;
1266 nreq->queue_entry.mem_ctx = nreq;
1267 nreq->queue_entry.vector = nreq->out.vector;
1268 nreq->queue_entry.count = nreq->out.vector_count;
1269 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1270 xconn->smb2.send_queue_len++;
1272 status = smbd_smb2_flush_send_queue(xconn);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 return status;
1277 return NT_STATUS_OK;
1280 struct smbd_smb2_request_pending_state {
1281 struct smbd_smb2_send_queue queue_entry;
1282 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1283 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1286 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1287 struct tevent_timer *te,
1288 struct timeval current_time,
1289 void *private_data);
1291 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1292 struct tevent_req *subreq,
1293 uint32_t defer_time)
1295 NTSTATUS status;
1296 struct timeval defer_endtime;
1297 uint8_t *outhdr = NULL;
1298 uint32_t flags;
1300 if (!tevent_req_is_in_progress(subreq)) {
1302 * This is a performance optimization,
1303 * it avoids one tevent_loop iteration,
1304 * which means we avoid one
1305 * talloc_stackframe_pool/talloc_free pair.
1307 tevent_req_notify_callback(subreq);
1308 return NT_STATUS_OK;
1311 req->subreq = subreq;
1312 subreq = NULL;
1314 if (req->async_te) {
1315 /* We're already async. */
1316 return NT_STATUS_OK;
1319 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1320 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1321 if (flags & SMB2_HDR_FLAG_ASYNC) {
1322 /* We're already async. */
1323 return NT_STATUS_OK;
1326 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1328 * We're trying to go async in a compound
1329 * request chain.
1330 * This is only allowed for opens that
1331 * cause an oplock break, otherwise it
1332 * is not allowed. See [MS-SMB2].pdf
1333 * note <194> on Section 3.3.5.2.7.
1335 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1337 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1339 * Cancel the outstanding request.
1341 bool ok = tevent_req_cancel(req->subreq);
1342 if (ok) {
1343 return NT_STATUS_OK;
1345 TALLOC_FREE(req->subreq);
1346 return smbd_smb2_request_error(req,
1347 NT_STATUS_INTERNAL_ERROR);
1351 if (DEBUGLEVEL >= 10) {
1352 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1353 (unsigned int)req->current_idx );
1354 print_req_vectors(req);
1357 if (req->current_idx > 1) {
1359 * We're going async in a compound
1360 * chain after the first request has
1361 * already been processed. Send an
1362 * interim response containing the
1363 * set of replies already generated.
1365 int idx = req->current_idx;
1367 status = smb2_send_async_interim_response(req);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 return status;
1371 if (req->first_key.length > 0) {
1372 data_blob_clear_free(&req->first_key);
1375 req->current_idx = 1;
1378 * Re-arrange the in.vectors to remove what
1379 * we just sent.
1381 memmove(&req->in.vector[1],
1382 &req->in.vector[idx],
1383 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1384 req->in.vector_count = 1 + (req->in.vector_count - idx);
1386 /* Re-arrange the out.vectors to match. */
1387 memmove(&req->out.vector[1],
1388 &req->out.vector[idx],
1389 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1390 req->out.vector_count = 1 + (req->out.vector_count - idx);
1392 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1394 * We only have one remaining request as
1395 * we've processed everything else.
1396 * This is no longer a compound request.
1398 req->compound_related = false;
1399 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1400 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1401 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1404 if (req->last_key.length > 0) {
1405 data_blob_clear_free(&req->last_key);
1408 defer_endtime = timeval_current_ofs_usec(defer_time);
1409 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1410 req, defer_endtime,
1411 smbd_smb2_request_pending_timer,
1412 req);
1413 if (req->async_te == NULL) {
1414 return NT_STATUS_NO_MEMORY;
1417 return NT_STATUS_OK;
1420 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1421 struct tevent_timer *te,
1422 struct timeval current_time,
1423 void *private_data)
1425 struct smbd_smb2_request *req =
1426 talloc_get_type_abort(private_data,
1427 struct smbd_smb2_request);
1428 struct smbXsrv_connection *xconn = req->xconn;
1429 struct smbd_smb2_request_pending_state *state = NULL;
1430 uint8_t *outhdr = NULL;
1431 const uint8_t *inhdr = NULL;
1432 uint8_t *tf = NULL;
1433 size_t tf_len = 0;
1434 uint8_t *hdr = NULL;
1435 uint8_t *body = NULL;
1436 uint8_t *dyn = NULL;
1437 uint32_t flags = 0;
1438 uint64_t session_id = 0;
1439 uint64_t message_id = 0;
1440 uint64_t nonce_high = 0;
1441 uint64_t nonce_low = 0;
1442 uint64_t async_id = 0;
1443 NTSTATUS status;
1445 TALLOC_FREE(req->async_te);
1447 /* Ensure our final reply matches the interim one. */
1448 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1449 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1450 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1451 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1452 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1454 async_id = message_id; /* keep it simple for now... */
1456 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1457 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1459 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1460 "going async\n",
1461 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1462 (unsigned long long)async_id ));
1465 * What we send is identical to a smbd_smb2_request_error
1466 * packet with an error status of STATUS_PENDING. Make use
1467 * of this fact sometime when refactoring. JRA.
1470 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1471 if (state == NULL) {
1472 smbd_server_connection_terminate(req->sconn,
1473 nt_errstr(NT_STATUS_NO_MEMORY));
1474 return;
1477 tf = state->buf + NBT_HDR_SIZE;
1478 tf_len = SMB2_TF_HDR_SIZE;
1480 hdr = tf + SMB2_TF_HDR_SIZE;
1481 body = hdr + SMB2_HDR_BODY;
1482 dyn = body + 8;
1484 if (req->do_encryption) {
1485 struct smbXsrv_session *x = req->session;
1487 nonce_high = x->nonce_high;
1488 nonce_low = x->nonce_low;
1490 x->nonce_low += 1;
1491 if (x->nonce_low == 0) {
1492 x->nonce_low += 1;
1493 x->nonce_high += 1;
1497 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1498 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1499 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1500 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1502 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1503 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1504 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1505 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1506 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1508 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1509 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1510 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1511 SBVAL(hdr, SMB2_HDR_PID, async_id);
1512 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1513 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1514 memcpy(hdr+SMB2_HDR_SIGNATURE,
1515 outhdr+SMB2_HDR_SIGNATURE, 16);
1517 SSVAL(body, 0x00, 0x08 + 1);
1519 SCVAL(body, 0x02, 0);
1520 SCVAL(body, 0x03, 0);
1521 SIVAL(body, 0x04, 0);
1522 /* Match W2K8R2... */
1523 SCVAL(dyn, 0x00, 0x21);
1525 state->vector[0].iov_base = (void *)state->buf;
1526 state->vector[0].iov_len = NBT_HDR_SIZE;
1528 if (req->do_encryption) {
1529 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1530 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1531 } else {
1532 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1533 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1536 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1537 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1539 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1540 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1542 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1543 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1545 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1547 /* Ensure we correctly go through crediting. Grant
1548 the credits now, and zero credits on the final
1549 response. */
1550 smb2_set_operation_credit(req->xconn,
1551 SMBD_SMB2_IN_HDR_IOV(req),
1552 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1554 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1556 if (DEBUGLVL(10)) {
1557 int i;
1559 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1560 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1561 (unsigned int)i,
1562 (unsigned int)ARRAY_SIZE(state->vector),
1563 (unsigned int)state->vector[i].iov_len);
1567 if (req->do_encryption) {
1568 struct smbXsrv_session *x = req->session;
1569 DATA_BLOB encryption_key = x->global->encryption_key;
1571 status = smb2_signing_encrypt_pdu(encryption_key,
1572 xconn->protocol,
1573 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1574 SMBD_SMB2_NUM_IOV_PER_REQ);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 smbd_server_connection_terminate(req->sconn,
1577 nt_errstr(status));
1578 return;
1580 } else if (req->do_signing) {
1581 struct smbXsrv_session *x = req->session;
1582 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1584 status = smb2_signing_sign_pdu(signing_key,
1585 xconn->protocol,
1586 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1587 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 smbd_server_connection_terminate(req->sconn,
1590 nt_errstr(status));
1591 return;
1595 state->queue_entry.mem_ctx = state;
1596 state->queue_entry.vector = state->vector;
1597 state->queue_entry.count = ARRAY_SIZE(state->vector);
1598 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1599 xconn->smb2.send_queue_len++;
1601 status = smbd_smb2_flush_send_queue(xconn);
1602 if (!NT_STATUS_IS_OK(status)) {
1603 smbd_server_connection_terminate(req->sconn,
1604 nt_errstr(status));
1605 return;
1609 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1611 struct smbXsrv_connection *xconn = req->xconn;
1612 struct smbd_smb2_request *cur;
1613 const uint8_t *inhdr;
1614 uint32_t flags;
1615 uint64_t search_message_id;
1616 uint64_t search_async_id;
1617 uint64_t found_id;
1619 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1621 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1622 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1623 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1626 * we don't need the request anymore
1627 * cancel requests never have a response
1629 DLIST_REMOVE(xconn->smb2.requests, req);
1630 TALLOC_FREE(req);
1632 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1633 const uint8_t *outhdr;
1634 uint64_t message_id;
1635 uint64_t async_id;
1637 if (cur->compound_related) {
1639 * Never cancel anything in a compound request.
1640 * Way too hard to deal with the result.
1642 continue;
1645 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1647 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1648 async_id = BVAL(outhdr, SMB2_HDR_PID);
1650 if (flags & SMB2_HDR_FLAG_ASYNC) {
1651 if (search_async_id == async_id) {
1652 found_id = async_id;
1653 break;
1655 } else {
1656 if (search_message_id == message_id) {
1657 found_id = message_id;
1658 break;
1663 if (cur && cur->subreq) {
1664 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1665 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1666 "cancel opcode[%s] mid %llu\n",
1667 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1668 (unsigned long long)found_id ));
1669 tevent_req_cancel(cur->subreq);
1672 return NT_STATUS_OK;
1675 /*************************************************************
1676 Ensure an incoming tid is a valid one for us to access.
1677 Change to the associated uid credentials and chdir to the
1678 valid tid directory.
1679 *************************************************************/
1681 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1683 const uint8_t *inhdr;
1684 uint32_t in_flags;
1685 uint32_t in_tid;
1686 struct smbXsrv_tcon *tcon;
1687 NTSTATUS status;
1688 NTTIME now = timeval_to_nttime(&req->request_time);
1690 req->tcon = NULL;
1692 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1694 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1695 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1697 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1698 in_tid = req->last_tid;
1701 req->last_tid = 0;
1703 status = smb2srv_tcon_lookup(req->session,
1704 in_tid, now, &tcon);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 return status;
1709 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1710 return NT_STATUS_ACCESS_DENIED;
1713 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1714 if (!set_current_service(tcon->compat, 0, true)) {
1715 return NT_STATUS_ACCESS_DENIED;
1718 req->tcon = tcon;
1719 req->last_tid = in_tid;
1721 return NT_STATUS_OK;
1724 /*************************************************************
1725 Ensure an incoming session_id is a valid one for us to access.
1726 *************************************************************/
1728 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1730 const uint8_t *inhdr;
1731 uint32_t in_flags;
1732 uint16_t in_opcode;
1733 uint64_t in_session_id;
1734 struct smbXsrv_session *session = NULL;
1735 struct auth_session_info *session_info;
1736 NTSTATUS status;
1737 NTTIME now = timeval_to_nttime(&req->request_time);
1739 req->session = NULL;
1740 req->tcon = NULL;
1742 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1744 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1745 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1746 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1748 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1749 in_session_id = req->last_session_id;
1752 req->last_session_id = 0;
1754 /* lookup an existing session */
1755 status = smb2srv_session_lookup(req->xconn,
1756 in_session_id, now,
1757 &session);
1758 if (session) {
1759 req->session = session;
1760 req->last_session_id = in_session_id;
1762 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1763 switch (in_opcode) {
1764 case SMB2_OP_SESSSETUP:
1765 status = NT_STATUS_OK;
1766 break;
1767 default:
1768 break;
1771 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1772 switch (in_opcode) {
1773 case SMB2_OP_TCON:
1774 case SMB2_OP_CREATE:
1775 case SMB2_OP_GETINFO:
1776 case SMB2_OP_SETINFO:
1777 return NT_STATUS_INVALID_HANDLE;
1778 default:
1780 * Notice the check for
1781 * (session_info == NULL)
1782 * below.
1784 status = NT_STATUS_OK;
1785 break;
1788 if (!NT_STATUS_IS_OK(status)) {
1789 return status;
1792 session_info = session->global->auth_session_info;
1793 if (session_info == NULL) {
1794 return NT_STATUS_INVALID_HANDLE;
1797 if (in_session_id != req->xconn->last_session_id) {
1798 req->xconn->last_session_id = in_session_id;
1799 set_current_user_info(session_info->unix_info->sanitized_username,
1800 session_info->unix_info->unix_name,
1801 session_info->info->domain_name);
1804 return NT_STATUS_OK;
1807 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1808 uint32_t data_length)
1810 struct smbXsrv_connection *xconn = req->sconn->conn;
1811 uint16_t needed_charge;
1812 uint16_t credit_charge = 1;
1813 const uint8_t *inhdr;
1815 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1817 if (xconn->smb2.credits.multicredit) {
1818 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1819 credit_charge = MAX(credit_charge, 1);
1822 needed_charge = (data_length - 1)/ 65536 + 1;
1824 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1825 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1826 credit_charge, needed_charge));
1828 if (needed_charge > credit_charge) {
1829 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1830 credit_charge, needed_charge));
1831 return NT_STATUS_INVALID_PARAMETER;
1834 return NT_STATUS_OK;
1837 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1838 size_t expected_body_size)
1840 struct iovec *inhdr_v;
1841 const uint8_t *inhdr;
1842 uint16_t opcode;
1843 const uint8_t *inbody;
1844 size_t body_size;
1845 size_t min_dyn_size = expected_body_size & 0x00000001;
1846 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1849 * The following should be checked already.
1851 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1852 return NT_STATUS_INTERNAL_ERROR;
1854 if (req->current_idx > max_idx) {
1855 return NT_STATUS_INTERNAL_ERROR;
1858 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1859 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1860 return NT_STATUS_INTERNAL_ERROR;
1862 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1863 return NT_STATUS_INTERNAL_ERROR;
1866 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1867 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1869 switch (opcode) {
1870 case SMB2_OP_IOCTL:
1871 case SMB2_OP_GETINFO:
1872 min_dyn_size = 0;
1873 break;
1874 case SMB2_OP_WRITE:
1875 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1876 if (req->smb1req->unread_bytes < min_dyn_size) {
1877 return NT_STATUS_INVALID_PARAMETER;
1880 min_dyn_size = 0;
1882 break;
1886 * Now check the expected body size,
1887 * where the last byte might be in the
1888 * dynamic section..
1890 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1891 return NT_STATUS_INVALID_PARAMETER;
1893 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1894 return NT_STATUS_INVALID_PARAMETER;
1897 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1899 body_size = SVAL(inbody, 0x00);
1900 if (body_size != expected_body_size) {
1901 return NT_STATUS_INVALID_PARAMETER;
1904 return NT_STATUS_OK;
1907 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1909 struct smbXsrv_connection *xconn = req->sconn->conn;
1910 const struct smbd_smb2_dispatch_table *call = NULL;
1911 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1912 const uint8_t *inhdr;
1913 uint16_t opcode;
1914 uint32_t flags;
1915 uint64_t mid;
1916 NTSTATUS status;
1917 NTSTATUS session_status;
1918 uint32_t allowed_flags;
1919 NTSTATUS return_value;
1920 struct smbXsrv_session *x = NULL;
1921 bool signing_required = false;
1922 bool encryption_required = false;
1924 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1926 /* TODO: verify more things */
1928 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1929 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1930 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1931 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1932 smb2_opcode_name(opcode),
1933 (unsigned long long)mid));
1935 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1937 * once the protocol is negotiated
1938 * SMB2_OP_NEGPROT is not allowed anymore
1940 if (opcode == SMB2_OP_NEGPROT) {
1941 /* drop the connection */
1942 return NT_STATUS_INVALID_PARAMETER;
1944 } else {
1946 * if the protocol is not negotiated yet
1947 * only SMB2_OP_NEGPROT is allowed.
1949 if (opcode != SMB2_OP_NEGPROT) {
1950 /* drop the connection */
1951 return NT_STATUS_INVALID_PARAMETER;
1956 * Check if the client provided a valid session id,
1957 * if so smbd_smb2_request_check_session() calls
1958 * set_current_user_info().
1960 * As some command don't require a valid session id
1961 * we defer the check of the session_status
1963 session_status = smbd_smb2_request_check_session(req);
1964 x = req->session;
1965 if (x != NULL) {
1966 signing_required = x->global->signing_required;
1967 encryption_required = x->global->encryption_required;
1969 if (opcode == SMB2_OP_SESSSETUP &&
1970 x->global->channels[0].signing_key.length) {
1971 signing_required = true;
1975 req->do_signing = false;
1976 req->do_encryption = false;
1977 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1978 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1979 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1981 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1982 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1983 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1984 (unsigned long long)x->global->session_wire_id,
1985 (unsigned long long)tf_session_id));
1987 * TODO: windows allows this...
1988 * should we drop the connection?
1990 * For now we just return ACCESS_DENIED
1991 * (Windows clients never trigger this)
1992 * and wait for an update of [MS-SMB2].
1994 return smbd_smb2_request_error(req,
1995 NT_STATUS_ACCESS_DENIED);
1998 req->do_encryption = true;
2001 if (encryption_required && !req->do_encryption) {
2002 return smbd_smb2_request_error(req,
2003 NT_STATUS_ACCESS_DENIED);
2006 call = smbd_smb2_call(opcode);
2007 if (call == NULL) {
2008 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2011 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2012 SMB2_HDR_FLAG_SIGNED |
2013 SMB2_HDR_FLAG_DFS;
2014 if (opcode == SMB2_OP_CANCEL) {
2015 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2017 if ((flags & ~allowed_flags) != 0) {
2018 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2021 if (flags & SMB2_HDR_FLAG_CHAINED) {
2023 * This check is mostly for giving the correct error code
2024 * for compounded requests.
2026 if (!NT_STATUS_IS_OK(session_status)) {
2027 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2029 } else {
2030 req->compat_chain_fsp = NULL;
2033 if (req->do_encryption) {
2034 signing_required = false;
2035 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2036 DATA_BLOB signing_key;
2038 if (x == NULL) {
2040 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2041 * If the SMB2 header of the SMB2 NEGOTIATE
2042 * request has the SMB2_FLAGS_SIGNED bit set in the
2043 * Flags field, the server MUST fail the request
2044 * with STATUS_INVALID_PARAMETER.
2046 * Microsoft test tool checks this.
2049 if ((opcode == SMB2_OP_NEGPROT) &&
2050 (flags & SMB2_HDR_FLAG_SIGNED)) {
2051 status = NT_STATUS_INVALID_PARAMETER;
2052 } else {
2053 status = NT_STATUS_USER_SESSION_DELETED;
2055 return smbd_smb2_request_error(req, status);
2058 signing_key = x->global->channels[0].signing_key;
2061 * If we have a signing key, we should
2062 * sign the response
2064 if (signing_key.length > 0) {
2065 req->do_signing = true;
2068 status = smb2_signing_check_pdu(signing_key,
2069 xconn->protocol,
2070 SMBD_SMB2_IN_HDR_IOV(req),
2071 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2072 if (!NT_STATUS_IS_OK(status)) {
2073 return smbd_smb2_request_error(req, status);
2077 * Now that we know the request was correctly signed
2078 * we have to sign the response too.
2080 req->do_signing = true;
2082 if (!NT_STATUS_IS_OK(session_status)) {
2083 return smbd_smb2_request_error(req, session_status);
2085 } else if (opcode == SMB2_OP_CANCEL) {
2086 /* Cancel requests are allowed to skip the signing */
2087 } else if (signing_required) {
2089 * If signing is required we try to sign
2090 * a possible error response
2092 req->do_signing = true;
2093 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2096 if (flags & SMB2_HDR_FLAG_CHAINED) {
2097 req->compound_related = true;
2100 if (call->need_session) {
2101 if (!NT_STATUS_IS_OK(session_status)) {
2102 return smbd_smb2_request_error(req, session_status);
2106 if (call->need_tcon) {
2107 SMB_ASSERT(call->need_session);
2110 * This call needs to be run as user.
2112 * smbd_smb2_request_check_tcon()
2113 * calls change_to_user() on success.
2115 status = smbd_smb2_request_check_tcon(req);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 return smbd_smb2_request_error(req, status);
2119 if (req->tcon->global->encryption_required) {
2120 encryption_required = true;
2122 if (encryption_required && !req->do_encryption) {
2123 return smbd_smb2_request_error(req,
2124 NT_STATUS_ACCESS_DENIED);
2128 if (call->fileid_ofs != 0) {
2129 size_t needed = call->fileid_ofs + 16;
2130 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2131 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2132 uint64_t file_id_persistent;
2133 uint64_t file_id_volatile;
2134 struct files_struct *fsp;
2136 SMB_ASSERT(call->need_tcon);
2138 if (needed > body_size) {
2139 return smbd_smb2_request_error(req,
2140 NT_STATUS_INVALID_PARAMETER);
2143 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2144 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2146 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2147 if (fsp == NULL) {
2148 if (!call->allow_invalid_fileid) {
2149 return smbd_smb2_request_error(req,
2150 NT_STATUS_FILE_CLOSED);
2153 if (file_id_persistent != UINT64_MAX) {
2154 return smbd_smb2_request_error(req,
2155 NT_STATUS_FILE_CLOSED);
2157 if (file_id_volatile != UINT64_MAX) {
2158 return smbd_smb2_request_error(req,
2159 NT_STATUS_FILE_CLOSED);
2164 if (call->as_root) {
2165 SMB_ASSERT(call->fileid_ofs == 0);
2166 /* This call needs to be run as root */
2167 change_to_root_user();
2168 } else {
2169 SMB_ASSERT(call->need_tcon);
2172 switch (opcode) {
2173 case SMB2_OP_NEGPROT:
2175 START_PROFILE(smb2_negprot);
2176 return_value = smbd_smb2_request_process_negprot(req);
2177 END_PROFILE(smb2_negprot);
2179 break;
2181 case SMB2_OP_SESSSETUP:
2183 START_PROFILE(smb2_sesssetup);
2184 return_value = smbd_smb2_request_process_sesssetup(req);
2185 END_PROFILE(smb2_sesssetup);
2187 break;
2189 case SMB2_OP_LOGOFF:
2191 START_PROFILE(smb2_logoff);
2192 return_value = smbd_smb2_request_process_logoff(req);
2193 END_PROFILE(smb2_logoff);
2195 break;
2197 case SMB2_OP_TCON:
2199 START_PROFILE(smb2_tcon);
2200 return_value = smbd_smb2_request_process_tcon(req);
2201 END_PROFILE(smb2_tcon);
2203 break;
2205 case SMB2_OP_TDIS:
2207 START_PROFILE(smb2_tdis);
2208 return_value = smbd_smb2_request_process_tdis(req);
2209 END_PROFILE(smb2_tdis);
2211 break;
2213 case SMB2_OP_CREATE:
2215 START_PROFILE(smb2_create);
2216 return_value = smbd_smb2_request_process_create(req);
2217 END_PROFILE(smb2_create);
2219 break;
2221 case SMB2_OP_CLOSE:
2223 START_PROFILE(smb2_close);
2224 return_value = smbd_smb2_request_process_close(req);
2225 END_PROFILE(smb2_close);
2227 break;
2229 case SMB2_OP_FLUSH:
2231 START_PROFILE(smb2_flush);
2232 return_value = smbd_smb2_request_process_flush(req);
2233 END_PROFILE(smb2_flush);
2235 break;
2237 case SMB2_OP_READ:
2239 START_PROFILE(smb2_read);
2240 return_value = smbd_smb2_request_process_read(req);
2241 END_PROFILE(smb2_read);
2243 break;
2245 case SMB2_OP_WRITE:
2247 START_PROFILE(smb2_write);
2248 return_value = smbd_smb2_request_process_write(req);
2249 END_PROFILE(smb2_write);
2251 break;
2253 case SMB2_OP_LOCK:
2255 START_PROFILE(smb2_lock);
2256 return_value = smbd_smb2_request_process_lock(req);
2257 END_PROFILE(smb2_lock);
2259 break;
2261 case SMB2_OP_IOCTL:
2263 START_PROFILE(smb2_ioctl);
2264 return_value = smbd_smb2_request_process_ioctl(req);
2265 END_PROFILE(smb2_ioctl);
2267 break;
2269 case SMB2_OP_CANCEL:
2271 START_PROFILE(smb2_cancel);
2272 return_value = smbd_smb2_request_process_cancel(req);
2273 END_PROFILE(smb2_cancel);
2275 break;
2277 case SMB2_OP_KEEPALIVE:
2279 START_PROFILE(smb2_keepalive);
2280 return_value = smbd_smb2_request_process_keepalive(req);
2281 END_PROFILE(smb2_keepalive);
2283 break;
2285 case SMB2_OP_FIND:
2287 START_PROFILE(smb2_find);
2288 return_value = smbd_smb2_request_process_find(req);
2289 END_PROFILE(smb2_find);
2291 break;
2293 case SMB2_OP_NOTIFY:
2295 START_PROFILE(smb2_notify);
2296 return_value = smbd_smb2_request_process_notify(req);
2297 END_PROFILE(smb2_notify);
2299 break;
2301 case SMB2_OP_GETINFO:
2303 START_PROFILE(smb2_getinfo);
2304 return_value = smbd_smb2_request_process_getinfo(req);
2305 END_PROFILE(smb2_getinfo);
2307 break;
2309 case SMB2_OP_SETINFO:
2311 START_PROFILE(smb2_setinfo);
2312 return_value = smbd_smb2_request_process_setinfo(req);
2313 END_PROFILE(smb2_setinfo);
2315 break;
2317 case SMB2_OP_BREAK:
2319 START_PROFILE(smb2_break);
2320 return_value = smbd_smb2_request_process_break(req);
2321 END_PROFILE(smb2_break);
2323 break;
2325 default:
2326 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2327 break;
2329 return return_value;
2332 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2334 struct smbXsrv_connection *xconn = req->xconn;
2335 int first_idx = 1;
2336 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2337 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2338 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2339 NTSTATUS status;
2341 req->subreq = NULL;
2342 TALLOC_FREE(req->async_te);
2344 if (req->do_encryption &&
2345 (firsttf->iov_len == 0) &&
2346 (req->first_key.length == 0) &&
2347 (req->session != NULL) &&
2348 (req->session->global->encryption_key.length != 0))
2350 DATA_BLOB encryption_key = req->session->global->encryption_key;
2351 uint8_t *tf;
2352 uint64_t session_id = req->session->global->session_wire_id;
2353 struct smbXsrv_session *x = req->session;
2354 uint64_t nonce_high;
2355 uint64_t nonce_low;
2357 nonce_high = x->nonce_high;
2358 nonce_low = x->nonce_low;
2360 x->nonce_low += 1;
2361 if (x->nonce_low == 0) {
2362 x->nonce_low += 1;
2363 x->nonce_high += 1;
2367 * We need to place the SMB2_TRANSFORM header before the
2368 * first SMB2 header
2372 * we need to remember the encryption key
2373 * and defer the signing/encryption until
2374 * we are sure that we do not change
2375 * the header again.
2377 req->first_key = data_blob_dup_talloc(req, encryption_key);
2378 if (req->first_key.data == NULL) {
2379 return NT_STATUS_NO_MEMORY;
2382 tf = talloc_zero_array(req, uint8_t,
2383 SMB2_TF_HDR_SIZE);
2384 if (tf == NULL) {
2385 return NT_STATUS_NO_MEMORY;
2388 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2389 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2390 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2391 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2393 firsttf->iov_base = (void *)tf;
2394 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2397 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2398 (req->last_key.length > 0) &&
2399 (firsttf->iov_len == 0))
2401 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2402 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2405 * As we are sure the header of the last request in the
2406 * compound chain will not change, we can to sign here
2407 * with the last signing key we remembered.
2409 status = smb2_signing_sign_pdu(req->last_key,
2410 xconn->protocol,
2411 lasthdr,
2412 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2413 if (!NT_STATUS_IS_OK(status)) {
2414 return status;
2417 if (req->last_key.length > 0) {
2418 data_blob_clear_free(&req->last_key);
2421 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2423 if (req->current_idx < req->out.vector_count) {
2425 * We must process the remaining compound
2426 * SMB2 requests before any new incoming SMB2
2427 * requests. This is because incoming SMB2
2428 * requests may include a cancel for a
2429 * compound request we haven't processed
2430 * yet.
2432 struct tevent_immediate *im = tevent_create_immediate(req);
2433 if (!im) {
2434 return NT_STATUS_NO_MEMORY;
2437 if (req->do_signing && firsttf->iov_len == 0) {
2438 struct smbXsrv_session *x = req->session;
2439 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2442 * we need to remember the signing key
2443 * and defer the signing until
2444 * we are sure that we do not change
2445 * the header again.
2447 req->last_key = data_blob_dup_talloc(req, signing_key);
2448 if (req->last_key.data == NULL) {
2449 return NT_STATUS_NO_MEMORY;
2453 tevent_schedule_immediate(im,
2454 req->sconn->ev_ctx,
2455 smbd_smb2_request_dispatch_immediate,
2456 req);
2457 return NT_STATUS_OK;
2460 if (req->compound_related) {
2461 req->compound_related = false;
2464 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2466 /* Set credit for these operations (zero credits if this
2467 is a final reply for an async operation). */
2468 smb2_calculate_credits(req, req);
2471 * now check if we need to sign the current response
2473 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2474 status = smb2_signing_encrypt_pdu(req->first_key,
2475 xconn->protocol,
2476 firsttf,
2477 req->out.vector_count - first_idx);
2478 if (!NT_STATUS_IS_OK(status)) {
2479 return status;
2481 } else if (req->do_signing) {
2482 struct smbXsrv_session *x = req->session;
2483 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2485 status = smb2_signing_sign_pdu(signing_key,
2486 xconn->protocol,
2487 outhdr,
2488 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 return status;
2493 if (req->first_key.length > 0) {
2494 data_blob_clear_free(&req->first_key);
2497 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2498 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2499 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2500 /* Dynamic part is NULL. Chop it off,
2501 We're going to send it via sendfile. */
2502 req->out.vector_count -= 1;
2506 * We're done with this request -
2507 * move it off the "being processed" queue.
2509 DLIST_REMOVE(xconn->smb2.requests, req);
2511 req->queue_entry.mem_ctx = req;
2512 req->queue_entry.vector = req->out.vector;
2513 req->queue_entry.count = req->out.vector_count;
2514 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2515 xconn->smb2.send_queue_len++;
2517 status = smbd_smb2_flush_send_queue(xconn);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 return status;
2522 return NT_STATUS_OK;
2525 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2527 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2528 struct tevent_immediate *im,
2529 void *private_data)
2531 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2532 struct smbd_smb2_request);
2533 struct smbd_server_connection *sconn = req->sconn;
2534 struct smbXsrv_connection *xconn = req->xconn;
2535 NTSTATUS status;
2537 TALLOC_FREE(im);
2539 if (DEBUGLEVEL >= 10) {
2540 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2541 req->current_idx, req->in.vector_count));
2542 print_req_vectors(req);
2545 status = smbd_smb2_request_dispatch(req);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 smbd_server_connection_terminate(sconn, nt_errstr(status));
2548 return;
2551 status = smbd_smb2_request_next_incoming(xconn);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554 return;
2558 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2559 NTSTATUS status,
2560 DATA_BLOB body, DATA_BLOB *dyn,
2561 const char *location)
2563 uint8_t *outhdr;
2564 struct iovec *outbody_v;
2565 struct iovec *outdyn_v;
2566 uint32_t next_command_ofs;
2568 DEBUG(10,("smbd_smb2_request_done_ex: "
2569 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2570 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2571 dyn ? "yes": "no",
2572 (unsigned int)(dyn ? dyn->length : 0),
2573 location));
2575 if (body.length < 2) {
2576 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2579 if ((body.length % 2) != 0) {
2580 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2583 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2584 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2585 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2587 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2588 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2590 outbody_v->iov_base = (void *)body.data;
2591 outbody_v->iov_len = body.length;
2593 if (dyn) {
2594 outdyn_v->iov_base = (void *)dyn->data;
2595 outdyn_v->iov_len = dyn->length;
2596 } else {
2597 outdyn_v->iov_base = NULL;
2598 outdyn_v->iov_len = 0;
2601 /* see if we need to recalculate the offset to the next response */
2602 if (next_command_ofs > 0) {
2603 next_command_ofs = SMB2_HDR_BODY;
2604 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2605 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2608 if ((next_command_ofs % 8) != 0) {
2609 size_t pad_size = 8 - (next_command_ofs % 8);
2610 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2612 * if the dyn buffer is empty
2613 * we can use it to add padding
2615 uint8_t *pad;
2617 pad = talloc_zero_array(req,
2618 uint8_t, pad_size);
2619 if (pad == NULL) {
2620 return smbd_smb2_request_error(req,
2621 NT_STATUS_NO_MEMORY);
2624 outdyn_v->iov_base = (void *)pad;
2625 outdyn_v->iov_len = pad_size;
2626 } else {
2628 * For now we copy the dynamic buffer
2629 * and add the padding to the new buffer
2631 size_t old_size;
2632 uint8_t *old_dyn;
2633 size_t new_size;
2634 uint8_t *new_dyn;
2636 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2637 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2639 new_size = old_size + pad_size;
2640 new_dyn = talloc_zero_array(req,
2641 uint8_t, new_size);
2642 if (new_dyn == NULL) {
2643 return smbd_smb2_request_error(req,
2644 NT_STATUS_NO_MEMORY);
2647 memcpy(new_dyn, old_dyn, old_size);
2648 memset(new_dyn + old_size, 0, pad_size);
2650 outdyn_v->iov_base = (void *)new_dyn;
2651 outdyn_v->iov_len = new_size;
2653 next_command_ofs += pad_size;
2656 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2658 return smbd_smb2_request_reply(req);
2661 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2662 NTSTATUS status,
2663 DATA_BLOB *info,
2664 const char *location)
2666 struct smbXsrv_connection *xconn = req->sconn->conn;
2667 DATA_BLOB body;
2668 DATA_BLOB _dyn;
2669 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2670 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2672 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2673 req->current_idx, nt_errstr(status), info ? " +info" : "",
2674 location));
2676 if (unread_bytes) {
2677 /* Recvfile error. Drain incoming socket. */
2678 size_t ret;
2680 errno = 0;
2681 ret = drain_socket(xconn->transport.sock, unread_bytes);
2682 if (ret != unread_bytes) {
2683 NTSTATUS error;
2685 if (errno == 0) {
2686 error = NT_STATUS_IO_DEVICE_ERROR;
2687 } else {
2688 error = map_nt_error_from_unix_common(errno);
2691 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2692 "ret[%u] errno[%d] => %s\n",
2693 (unsigned)unread_bytes,
2694 (unsigned)ret, errno, nt_errstr(error)));
2695 return error;
2699 body.data = outhdr + SMB2_HDR_BODY;
2700 body.length = 8;
2701 SSVAL(body.data, 0, 9);
2703 if (info) {
2704 SIVAL(body.data, 0x04, info->length);
2705 } else {
2706 /* Allocated size of req->out.vector[i].iov_base
2707 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2708 * 1 byte without having to do an alloc.
2710 info = &_dyn;
2711 info->data = ((uint8_t *)outhdr) +
2712 OUTVEC_ALLOC_SIZE - 1;
2713 info->length = 1;
2714 SCVAL(info->data, 0, 0);
2718 * Note: Even if there is an error, continue to process the request.
2719 * per MS-SMB2.
2722 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2726 struct smbd_smb2_send_break_state {
2727 struct smbd_server_connection *sconn;
2728 struct smbd_smb2_send_queue queue_entry;
2729 uint8_t nbt_hdr[NBT_HDR_SIZE];
2730 uint8_t tf[SMB2_TF_HDR_SIZE];
2731 uint8_t hdr[SMB2_HDR_BODY];
2732 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2733 uint8_t body[1];
2736 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2737 struct smbXsrv_session *session,
2738 struct smbXsrv_tcon *tcon,
2739 const uint8_t *body,
2740 size_t body_len)
2742 struct smbd_smb2_send_break_state *state;
2743 struct smbXsrv_connection *xconn = sconn->conn;
2744 bool do_encryption = session->global->encryption_required;
2745 uint64_t nonce_high = 0;
2746 uint64_t nonce_low = 0;
2747 NTSTATUS status;
2748 size_t statelen;
2750 if (tcon->global->encryption_required) {
2751 do_encryption = true;
2754 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2755 body_len;
2757 state = talloc_zero_size(sconn, statelen);
2758 if (state == NULL) {
2759 return NT_STATUS_NO_MEMORY;
2761 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2762 state->sconn = sconn;
2764 if (do_encryption) {
2765 nonce_high = session->nonce_high;
2766 nonce_low = session->nonce_low;
2768 session->nonce_low += 1;
2769 if (session->nonce_low == 0) {
2770 session->nonce_low += 1;
2771 session->nonce_high += 1;
2775 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2776 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2777 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2778 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2780 SIVAL(state->hdr, 0, SMB2_MAGIC);
2781 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2782 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2783 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2784 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2785 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2786 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2787 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2788 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2789 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2790 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2791 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2792 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2794 state->vector[0] = (struct iovec) {
2795 .iov_base = state->nbt_hdr,
2796 .iov_len = sizeof(state->nbt_hdr)
2799 if (do_encryption) {
2800 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2801 .iov_base = state->tf,
2802 .iov_len = sizeof(state->tf)
2804 } else {
2805 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2806 .iov_base = NULL,
2807 .iov_len = 0
2811 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2812 .iov_base = state->hdr,
2813 .iov_len = sizeof(state->hdr)
2816 memcpy(state->body, body, body_len);
2818 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2819 .iov_base = state->body,
2820 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2824 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2827 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2829 if (do_encryption) {
2830 DATA_BLOB encryption_key = session->global->encryption_key;
2832 status = smb2_signing_encrypt_pdu(encryption_key,
2833 xconn->protocol,
2834 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2835 SMBD_SMB2_NUM_IOV_PER_REQ);
2836 if (!NT_STATUS_IS_OK(status)) {
2837 return status;
2841 state->queue_entry.mem_ctx = state;
2842 state->queue_entry.vector = state->vector;
2843 state->queue_entry.count = ARRAY_SIZE(state->vector);
2844 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2845 xconn->smb2.send_queue_len++;
2847 status = smbd_smb2_flush_send_queue(xconn);
2848 if (!NT_STATUS_IS_OK(status)) {
2849 return status;
2852 return NT_STATUS_OK;
2855 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2856 struct smbXsrv_session *session,
2857 struct smbXsrv_tcon *tcon,
2858 struct smbXsrv_open *op,
2859 uint8_t oplock_level)
2861 uint8_t body[0x18];
2863 SSVAL(body, 0x00, sizeof(body));
2864 SCVAL(body, 0x02, oplock_level);
2865 SCVAL(body, 0x03, 0); /* reserved */
2866 SIVAL(body, 0x04, 0); /* reserved */
2867 SBVAL(body, 0x08, op->global->open_persistent_id);
2868 SBVAL(body, 0x10, op->global->open_volatile_id);
2870 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2873 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2875 NTSTATUS status;
2876 uint32_t flags;
2877 uint64_t file_id_persistent;
2878 uint64_t file_id_volatile;
2879 struct smbXsrv_open *op = NULL;
2880 struct files_struct *fsp = NULL;
2881 const uint8_t *body = NULL;
2884 * This is only called with a pktbuf
2885 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2886 * bytes
2889 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2890 /* Transform header. Cannot recvfile. */
2891 return false;
2893 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2894 /* Not SMB2. Normal error path will cope. */
2895 return false;
2897 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2898 /* Not SMB2. Normal error path will cope. */
2899 return false;
2901 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2902 /* Needs to be a WRITE. */
2903 return false;
2905 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2906 /* Chained. Cannot recvfile. */
2907 return false;
2909 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2910 if (flags & SMB2_HDR_FLAG_CHAINED) {
2911 /* Chained. Cannot recvfile. */
2912 return false;
2914 if (flags & SMB2_HDR_FLAG_SIGNED) {
2915 /* Signed. Cannot recvfile. */
2916 return false;
2919 body = &state->pktbuf[SMB2_HDR_BODY];
2921 file_id_persistent = BVAL(body, 0x10);
2922 file_id_volatile = BVAL(body, 0x18);
2924 status = smb2srv_open_lookup(state->req->sconn->conn,
2925 file_id_persistent,
2926 file_id_volatile,
2927 0, /* now */
2928 &op);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 return false;
2933 fsp = op->compat;
2934 if (fsp == NULL) {
2935 return false;
2937 if (fsp->conn == NULL) {
2938 return false;
2941 if (IS_IPC(fsp->conn)) {
2942 return false;
2944 if (IS_PRINT(fsp->conn)) {
2945 return false;
2948 DEBUG(10,("Doing recvfile write len = %u\n",
2949 (unsigned int)(state->pktfull - state->pktlen)));
2951 return true;
2954 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2956 struct smbd_server_connection *sconn = xconn->sconn;
2957 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2958 size_t max_send_queue_len;
2959 size_t cur_send_queue_len;
2961 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2963 * we're not supposed to do any io
2965 return NT_STATUS_OK;
2968 if (state->req != NULL) {
2970 * if there is already a tstream_readv_pdu
2971 * pending, we are done.
2973 return NT_STATUS_OK;
2976 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2977 cur_send_queue_len = xconn->smb2.send_queue_len;
2979 if (cur_send_queue_len > max_send_queue_len) {
2981 * if we have a lot of requests to send,
2982 * we wait until they are on the wire until we
2983 * ask for the next request.
2985 return NT_STATUS_OK;
2988 /* ask for the next request */
2989 ZERO_STRUCTP(state);
2990 state->req = smbd_smb2_request_allocate(xconn);
2991 if (state->req == NULL) {
2992 return NT_STATUS_NO_MEMORY;
2994 state->req->sconn = sconn;
2995 state->req->xconn = xconn;
2996 state->min_recv_size = lp_min_receive_file_size();
2998 TEVENT_FD_READABLE(xconn->transport.fde);
3000 return NT_STATUS_OK;
3003 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3004 uint8_t *inbuf, size_t size)
3006 struct smbd_server_connection *sconn = xconn->sconn;
3007 NTSTATUS status;
3008 struct smbd_smb2_request *req = NULL;
3010 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3011 (unsigned int)size));
3013 status = smbd_initialize_smb2(xconn);
3014 if (!NT_STATUS_IS_OK(status)) {
3015 smbd_server_connection_terminate(sconn, nt_errstr(status));
3016 return;
3019 status = smbd_smb2_request_create(xconn, inbuf, size, &req);
3020 if (!NT_STATUS_IS_OK(status)) {
3021 smbd_server_connection_terminate(sconn, nt_errstr(status));
3022 return;
3025 status = smbd_smb2_request_validate(req);
3026 if (!NT_STATUS_IS_OK(status)) {
3027 smbd_server_connection_terminate(sconn, nt_errstr(status));
3028 return;
3031 status = smbd_smb2_request_setup_out(req);
3032 if (!NT_STATUS_IS_OK(status)) {
3033 smbd_server_connection_terminate(sconn, nt_errstr(status));
3034 return;
3037 status = smbd_smb2_request_dispatch(req);
3038 if (!NT_STATUS_IS_OK(status)) {
3039 smbd_server_connection_terminate(sconn, nt_errstr(status));
3040 return;
3043 status = smbd_smb2_request_next_incoming(xconn);
3044 if (!NT_STATUS_IS_OK(status)) {
3045 smbd_server_connection_terminate(sconn, nt_errstr(status));
3046 return;
3049 sconn->num_requests++;
3052 static int socket_error_from_errno(int ret,
3053 int sys_errno,
3054 bool *retry)
3056 *retry = false;
3058 if (ret >= 0) {
3059 return 0;
3062 if (ret != -1) {
3063 return EIO;
3066 if (sys_errno == 0) {
3067 return EIO;
3070 if (sys_errno == EINTR) {
3071 *retry = true;
3072 return sys_errno;
3075 if (sys_errno == EINPROGRESS) {
3076 *retry = true;
3077 return sys_errno;
3080 if (sys_errno == EAGAIN) {
3081 *retry = true;
3082 return sys_errno;
3085 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3086 if (sys_errno == ENOMEM) {
3087 *retry = true;
3088 return sys_errno;
3091 #ifdef EWOULDBLOCK
3092 #if EWOULDBLOCK != EAGAIN
3093 if (sys_errno == EWOULDBLOCK) {
3094 *retry = true;
3095 return sys_errno;
3097 #endif
3098 #endif
3100 return sys_errno;
3103 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3105 int ret;
3106 int err;
3107 bool retry;
3109 if (xconn->smb2.send_queue == NULL) {
3110 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3111 return NT_STATUS_OK;
3114 while (xconn->smb2.send_queue != NULL) {
3115 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3117 if (e->sendfile_header != NULL) {
3118 size_t size = 0;
3119 size_t i = 0;
3120 uint8_t *buf;
3122 for (i=0; i < e->count; i++) {
3123 size += e->vector[i].iov_len;
3126 if (size <= e->sendfile_header->length) {
3127 buf = e->sendfile_header->data;
3128 } else {
3129 buf = talloc_array(e->mem_ctx, uint8_t, size);
3130 if (buf == NULL) {
3131 return NT_STATUS_NO_MEMORY;
3135 size = 0;
3136 for (i=0; i < e->count; i++) {
3137 memcpy(buf+size,
3138 e->vector[i].iov_base,
3139 e->vector[i].iov_len);
3140 size += e->vector[i].iov_len;
3143 e->sendfile_header->data = buf;
3144 e->sendfile_header->length = size;
3145 e->count = 0;
3147 xconn->smb2.send_queue_len--;
3148 DLIST_REMOVE(xconn->smb2.send_queue, e);
3150 * This triggers the sendfile path via
3151 * the destructor.
3153 talloc_free(e->mem_ctx);
3154 continue;
3157 ret = writev(xconn->transport.sock, e->vector, e->count);
3158 if (ret == 0) {
3159 /* propagate end of file */
3160 return NT_STATUS_INTERNAL_ERROR;
3162 err = socket_error_from_errno(ret, errno, &retry);
3163 if (retry) {
3164 /* retry later */
3165 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3166 return NT_STATUS_OK;
3168 if (err != 0) {
3169 return map_nt_error_from_unix_common(err);
3171 while (ret > 0) {
3172 if (ret < e->vector[0].iov_len) {
3173 uint8_t *base;
3174 base = (uint8_t *)e->vector[0].iov_base;
3175 base += ret;
3176 e->vector[0].iov_base = (void *)base;
3177 e->vector[0].iov_len -= ret;
3178 break;
3180 ret -= e->vector[0].iov_len;
3181 e->vector += 1;
3182 e->count -= 1;
3186 * there're maybe some empty vectors at the end
3187 * which we need to skip, otherwise we would get
3188 * ret == 0 from the readv() call and return EPIPE
3190 while (e->count > 0) {
3191 if (e->vector[0].iov_len > 0) {
3192 break;
3194 e->vector += 1;
3195 e->count -= 1;
3198 if (e->count > 0) {
3199 /* we have more to write */
3200 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3201 return NT_STATUS_OK;
3204 xconn->smb2.send_queue_len--;
3205 DLIST_REMOVE(xconn->smb2.send_queue, e);
3206 talloc_free(e->mem_ctx);
3209 return NT_STATUS_OK;
3212 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3213 uint16_t fde_flags)
3215 struct smbd_server_connection *sconn = xconn->sconn;
3216 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3217 struct smbd_smb2_request *req = NULL;
3218 size_t min_recvfile_size = UINT32_MAX;
3219 int ret;
3220 int err;
3221 bool retry;
3222 NTSTATUS status;
3223 NTTIME now;
3225 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3227 * we're not supposed to do any io
3229 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3230 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3231 return NT_STATUS_OK;
3234 if (fde_flags & TEVENT_FD_WRITE) {
3235 status = smbd_smb2_flush_send_queue(xconn);
3236 if (!NT_STATUS_IS_OK(status)) {
3237 return status;
3241 if (!(fde_flags & TEVENT_FD_READ)) {
3242 return NT_STATUS_OK;
3245 if (state->req == NULL) {
3246 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3247 return NT_STATUS_OK;
3250 again:
3251 if (!state->hdr.done) {
3252 state->hdr.done = true;
3254 state->vector.iov_base = (void *)state->hdr.nbt;
3255 state->vector.iov_len = NBT_HDR_SIZE;
3258 ret = readv(xconn->transport.sock, &state->vector, 1);
3259 if (ret == 0) {
3260 /* propagate end of file */
3261 return NT_STATUS_END_OF_FILE;
3263 err = socket_error_from_errno(ret, errno, &retry);
3264 if (retry) {
3265 /* retry later */
3266 TEVENT_FD_READABLE(xconn->transport.fde);
3267 return NT_STATUS_OK;
3269 if (err != 0) {
3270 return map_nt_error_from_unix_common(err);
3273 if (ret < state->vector.iov_len) {
3274 uint8_t *base;
3275 base = (uint8_t *)state->vector.iov_base;
3276 base += ret;
3277 state->vector.iov_base = (void *)base;
3278 state->vector.iov_len -= ret;
3279 /* we have more to read */
3280 TEVENT_FD_READABLE(xconn->transport.fde);
3281 return NT_STATUS_OK;
3284 if (state->pktlen > 0) {
3285 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3287 * Not a possible receivefile write.
3288 * Read the rest of the data.
3290 state->doing_receivefile = false;
3292 state->pktbuf = talloc_realloc(state->req,
3293 state->pktbuf,
3294 uint8_t,
3295 state->pktfull);
3296 if (state->pktbuf == NULL) {
3297 return NT_STATUS_NO_MEMORY;
3300 state->vector.iov_base = (void *)(state->pktbuf +
3301 state->pktlen);
3302 state->vector.iov_len = (state->pktfull -
3303 state->pktlen);
3305 state->pktlen = state->pktfull;
3306 goto again;
3310 * Either this is a receivefile write so we've
3311 * done a short read, or if not we have all the data.
3313 goto got_full;
3317 * Now we analyze the NBT header
3319 if (state->hdr.nbt[0] != 0x00) {
3320 state->min_recv_size = 0;
3322 state->pktfull = smb2_len(state->hdr.nbt);
3323 if (state->pktfull == 0) {
3324 goto got_full;
3327 if (state->min_recv_size != 0) {
3328 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3329 min_recvfile_size += state->min_recv_size;
3332 if (state->pktfull > min_recvfile_size) {
3334 * Might be a receivefile write. Read the SMB2 HEADER +
3335 * SMB2_WRITE header first. Set 'doing_receivefile'
3336 * as we're *attempting* receivefile write. If this
3337 * turns out not to be a SMB2_WRITE request or otherwise
3338 * not suitable then we'll just read the rest of the data
3339 * the next time this function is called.
3341 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3342 state->doing_receivefile = true;
3343 } else {
3344 state->pktlen = state->pktfull;
3347 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3348 if (state->pktbuf == NULL) {
3349 return NT_STATUS_NO_MEMORY;
3352 state->vector.iov_base = (void *)state->pktbuf;
3353 state->vector.iov_len = state->pktlen;
3355 goto again;
3357 got_full:
3359 if (state->hdr.nbt[0] != 0x00) {
3360 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3361 state->hdr.nbt[0]));
3363 req = state->req;
3364 ZERO_STRUCTP(state);
3365 state->req = req;
3366 state->min_recv_size = lp_min_receive_file_size();
3367 req = NULL;
3368 goto again;
3371 req = state->req;
3372 state->req = NULL;
3374 req->request_time = timeval_current();
3375 now = timeval_to_nttime(&req->request_time);
3377 status = smbd_smb2_inbuf_parse_compound(xconn,
3378 now,
3379 state->pktbuf,
3380 state->pktlen,
3381 req,
3382 &req->in.vector,
3383 &req->in.vector_count);
3384 if (!NT_STATUS_IS_OK(status)) {
3385 return status;
3388 if (state->doing_receivefile) {
3389 req->smb1req = talloc_zero(req, struct smb_request);
3390 if (req->smb1req == NULL) {
3391 return NT_STATUS_NO_MEMORY;
3393 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3396 ZERO_STRUCTP(state);
3398 req->current_idx = 1;
3400 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3401 req->current_idx, req->in.vector_count));
3403 status = smbd_smb2_request_validate(req);
3404 if (!NT_STATUS_IS_OK(status)) {
3405 return status;
3408 status = smbd_smb2_request_setup_out(req);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 return status;
3413 status = smbd_smb2_request_dispatch(req);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 return status;
3418 sconn->num_requests++;
3420 /* The timeout_processing function isn't run nearly
3421 often enough to implement 'max log size' without
3422 overrunning the size of the file by many megabytes.
3423 This is especially true if we are running at debug
3424 level 10. Checking every 50 SMB2s is a nice
3425 tradeoff of performance vs log file size overrun. */
3427 if ((sconn->num_requests % 50) == 0 &&
3428 need_to_check_log_size()) {
3429 change_to_root_user();
3430 check_log_size();
3433 status = smbd_smb2_request_next_incoming(xconn);
3434 if (!NT_STATUS_IS_OK(status)) {
3435 return status;
3438 return NT_STATUS_OK;
3441 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3442 struct tevent_fd *fde,
3443 uint16_t flags,
3444 void *private_data)
3446 struct smbXsrv_connection *xconn =
3447 talloc_get_type_abort(private_data,
3448 struct smbXsrv_connection);
3449 struct smbd_server_connection *sconn = xconn->sconn;
3450 NTSTATUS status;
3452 status = smbd_smb2_io_handler(xconn, flags);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 smbd_server_connection_terminate(sconn, nt_errstr(status));
3455 return;