ctdb:server: fix DEBUG message for wrong event script options.
[Samba.git] / source3 / smbd / smb2_server.c
blob69fe9e45c7f11dfb5da75eab1923fbc65a0ef2c4
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 smbd_server_connection *sconn);
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 smbd_server_connection *sconn)
203 TALLOC_FREE(sconn->smb1.fde);
205 sconn->smb2.send_queue = NULL;
207 sconn->smb2.seqnum_low = 0;
208 sconn->smb2.seqnum_range = 1;
209 sconn->smb2.credits_granted = 1;
210 sconn->smb2.max_credits = lp_smb2_max_credits();
211 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
212 sconn->smb2.max_credits);
213 if (sconn->smb2.credits_bitmap == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
218 sconn,
219 sconn->sock,
220 TEVENT_FD_READ,
221 smbd_smb2_connection_handler,
222 sconn);
223 if (sconn->smb2.fde == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(sconn->sock, false);
229 return NT_STATUS_OK;
232 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
233 #define _smb2_setlen(_buf,len) do { \
234 uint8_t *buf = (uint8_t *)_buf; \
235 buf[0] = 0; \
236 buf[1] = ((len)&0xFF0000)>>16; \
237 buf[2] = ((len)&0xFF00)>>8; \
238 buf[3] = (len)&0xFF; \
239 } while (0)
241 static void smb2_setup_nbt_length(struct iovec *vector, int count)
243 size_t len = 0;
244 int i;
246 for (i=1; i < count; i++) {
247 len += vector[i].iov_len;
250 _smb2_setlen(vector[0].iov_base, len);
253 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
255 if (req->first_key.length > 0) {
256 data_blob_clear_free(&req->first_key);
258 if (req->last_key.length > 0) {
259 data_blob_clear_free(&req->last_key);
261 return 0;
264 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
266 TALLOC_CTX *mem_pool;
267 struct smbd_smb2_request *req;
269 #if 0
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 #else
273 mem_pool = talloc_tos();
274 #endif
275 if (mem_pool == NULL) {
276 return NULL;
279 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 if (req == NULL) {
281 talloc_free(mem_pool);
282 return NULL;
284 talloc_reparent(mem_pool, mem_ctx, req);
285 #if 0
286 TALLOC_FREE(mem_pool);
287 #endif
289 req->last_session_id = UINT64_MAX;
290 req->last_tid = UINT32_MAX;
292 talloc_set_destructor(req, smbd_smb2_request_destructor);
294 return req;
297 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
298 NTTIME now,
299 uint8_t *buf,
300 size_t buflen,
301 struct smbd_smb2_request *req,
302 struct iovec **piov,
303 int *pnum_iov)
305 TALLOC_CTX *mem_ctx = req;
306 struct iovec *iov;
307 int num_iov = 1;
308 size_t taken = 0;
309 uint8_t *first_hdr = buf;
310 size_t verified_buflen = 0;
311 uint8_t *tf = NULL;
312 size_t tf_len = 0;
315 * Note: index '0' is reserved for the transport protocol
317 iov = req->in._vector;
319 while (taken < buflen) {
320 size_t len = buflen - taken;
321 uint8_t *hdr = first_hdr + taken;
322 struct iovec *cur;
323 size_t full_size;
324 size_t next_command_ofs;
325 uint16_t body_size;
326 uint8_t *body = NULL;
327 uint32_t dyn_size;
328 uint8_t *dyn = NULL;
329 struct iovec *iov_alloc = NULL;
331 if (iov != req->in._vector) {
332 iov_alloc = iov;
335 if (verified_buflen > taken) {
336 len = verified_buflen - taken;
337 } else {
338 tf = NULL;
339 tf_len = 0;
342 if (len < 4) {
343 DEBUG(10, ("%d bytes left, expected at least %d\n",
344 (int)len, 4));
345 goto inval;
347 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
348 struct smbXsrv_session *s = NULL;
349 uint64_t uid;
350 struct iovec tf_iov[2];
351 NTSTATUS status;
352 size_t enc_len;
354 if (conn->protocol < PROTOCOL_SMB2_24) {
355 DEBUG(10, ("Got SMB2_TRANSFORM header, "
356 "but dialect[0x%04X] is used\n",
357 conn->smb2.server.dialect));
358 goto inval;
361 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but not negotiated "
364 "client[0x%08X] server[0x%08X]\n",
365 conn->smb2.client.capabilities,
366 conn->smb2.server.capabilities));
367 goto inval;
370 if (len < SMB2_TF_HDR_SIZE) {
371 DEBUG(1, ("%d bytes left, expected at least %d\n",
372 (int)len, SMB2_TF_HDR_SIZE));
373 goto inval;
375 tf = hdr;
376 tf_len = SMB2_TF_HDR_SIZE;
377 taken += tf_len;
379 hdr = first_hdr + taken;
380 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
381 uid = BVAL(tf, SMB2_TF_SESSION_ID);
383 if (len < SMB2_TF_HDR_SIZE + enc_len) {
384 DEBUG(1, ("%d bytes left, expected at least %d\n",
385 (int)len,
386 (int)(SMB2_TF_HDR_SIZE + enc_len)));
387 goto inval;
390 status = smb2srv_session_lookup(conn, uid, now, &s);
391 if (s == NULL) {
392 DEBUG(1, ("invalid session[%llu] in "
393 "SMB2_TRANSFORM header\n",
394 (unsigned long long)uid));
395 TALLOC_FREE(iov_alloc);
396 return NT_STATUS_USER_SESSION_DELETED;
399 tf_iov[0].iov_base = (void *)tf;
400 tf_iov[0].iov_len = tf_len;
401 tf_iov[1].iov_base = (void *)hdr;
402 tf_iov[1].iov_len = enc_len;
404 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
405 conn->protocol,
406 tf_iov, 2);
407 if (!NT_STATUS_IS_OK(status)) {
408 TALLOC_FREE(iov_alloc);
409 return status;
412 verified_buflen = taken + enc_len;
413 len = enc_len;
417 * We need the header plus the body length field
420 if (len < SMB2_HDR_BODY + 2) {
421 DEBUG(10, ("%d bytes left, expected at least %d\n",
422 (int)len, SMB2_HDR_BODY));
423 goto inval;
425 if (IVAL(hdr, 0) != SMB2_MAGIC) {
426 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
427 IVAL(hdr, 0)));
428 goto inval;
430 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
431 DEBUG(10, ("Got HDR len %d, expected %d\n",
432 SVAL(hdr, 4), SMB2_HDR_BODY));
433 goto inval;
436 full_size = len;
437 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
438 body_size = SVAL(hdr, SMB2_HDR_BODY);
440 if (next_command_ofs != 0) {
441 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
442 goto inval;
444 if (next_command_ofs > full_size) {
445 goto inval;
447 full_size = next_command_ofs;
449 if (body_size < 2) {
450 goto inval;
452 body_size &= 0xfffe;
454 if (body_size > (full_size - SMB2_HDR_BODY)) {
456 * let the caller handle the error
458 body_size = full_size - SMB2_HDR_BODY;
460 body = hdr + SMB2_HDR_BODY;
461 dyn = body + body_size;
462 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
464 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
465 struct iovec *iov_tmp = NULL;
467 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
468 struct iovec,
469 num_iov +
470 SMBD_SMB2_NUM_IOV_PER_REQ);
471 if (iov_tmp == NULL) {
472 TALLOC_FREE(iov_alloc);
473 return NT_STATUS_NO_MEMORY;
476 if (iov_alloc == NULL) {
477 memcpy(iov_tmp,
478 req->in._vector,
479 sizeof(req->in._vector));
482 iov = iov_tmp;
484 cur = &iov[num_iov];
485 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
487 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
488 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
489 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
490 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
491 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
492 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
493 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
494 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
496 taken += full_size;
499 *piov = iov;
500 *pnum_iov = num_iov;
501 return NT_STATUS_OK;
503 inval:
504 if (iov != req->in._vector) {
505 TALLOC_FREE(iov);
507 return NT_STATUS_INVALID_PARAMETER;
510 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
511 uint8_t *inbuf, size_t size,
512 struct smbd_smb2_request **_req)
514 struct smbd_smb2_request *req;
515 uint32_t protocol_version;
516 const uint8_t *inhdr = NULL;
517 uint16_t cmd;
518 uint32_t next_command_ofs;
519 NTSTATUS status;
520 NTTIME now;
522 if (size < (4 + SMB2_HDR_BODY + 2)) {
523 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
524 return NT_STATUS_INVALID_PARAMETER;
527 inhdr = inbuf + 4;
529 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
530 if (protocol_version != SMB2_MAGIC) {
531 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
532 protocol_version));
533 return NT_STATUS_INVALID_PARAMETER;
536 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
537 if (cmd != SMB2_OP_NEGPROT) {
538 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
539 cmd));
540 return NT_STATUS_INVALID_PARAMETER;
543 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
544 if (next_command_ofs != 0) {
545 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
546 next_command_ofs));
547 return NT_STATUS_INVALID_PARAMETER;
550 req = smbd_smb2_request_allocate(sconn);
551 if (req == NULL) {
552 return NT_STATUS_NO_MEMORY;
554 req->sconn = sconn;
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(sconn->conn,
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 smbd_server_connection *sconn,
579 uint64_t message_id, uint64_t seq_id)
581 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
582 unsigned int offset;
584 if (seq_id < sconn->smb2.seqnum_low) {
585 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
586 "%llu (sequence id %llu) "
587 "(granted = %u, low = %llu, range = %u)\n",
588 (unsigned long long)message_id,
589 (unsigned long long)seq_id,
590 (unsigned int)sconn->smb2.credits_granted,
591 (unsigned long long)sconn->smb2.seqnum_low,
592 (unsigned int)sconn->smb2.seqnum_range));
593 return false;
596 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
597 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
598 "%llu (sequence id %llu) "
599 "(granted = %u, low = %llu, range = %u)\n",
600 (unsigned long long)message_id,
601 (unsigned long long)seq_id,
602 (unsigned int)sconn->smb2.credits_granted,
603 (unsigned long long)sconn->smb2.seqnum_low,
604 (unsigned int)sconn->smb2.seqnum_range));
605 return false;
608 offset = seq_id % sconn->smb2.max_credits;
610 if (bitmap_query(credits_bm, offset)) {
611 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
612 "%llu (sequence id %llu) "
613 "(granted = %u, low = %llu, range = %u) "
614 "(bm offset %u)\n",
615 (unsigned long long)message_id,
616 (unsigned long long)seq_id,
617 (unsigned int)sconn->smb2.credits_granted,
618 (unsigned long long)sconn->smb2.seqnum_low,
619 (unsigned int)sconn->smb2.seqnum_range,
620 offset));
621 return false;
624 /* Mark the message_ids as seen in the bitmap. */
625 bitmap_set(credits_bm, offset);
627 if (seq_id != sconn->smb2.seqnum_low) {
628 return true;
632 * Move the window forward by all the message_id's
633 * already seen.
635 while (bitmap_query(credits_bm, offset)) {
636 DEBUG(10,("smb2_validate_sequence_number: clearing "
637 "id %llu (position %u) from bitmap\n",
638 (unsigned long long)(sconn->smb2.seqnum_low),
639 offset));
640 bitmap_clear(credits_bm, offset);
642 sconn->smb2.seqnum_low += 1;
643 sconn->smb2.seqnum_range -= 1;
644 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
647 return true;
650 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
651 const uint8_t *inhdr)
653 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
654 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
655 uint16_t credit_charge = 1;
656 uint64_t i;
658 if (opcode == SMB2_OP_CANCEL) {
659 /* SMB2_CANCEL requests by definition resend messageids. */
660 return true;
663 if (sconn->smb2.supports_multicredit) {
664 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
665 credit_charge = MAX(credit_charge, 1);
668 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
669 "credits_granted %llu, "
670 "seqnum low/range: %llu/%llu\n",
671 (unsigned long long) message_id,
672 (unsigned long long) credit_charge,
673 (unsigned long long) sconn->smb2.credits_granted,
674 (unsigned long long) sconn->smb2.seqnum_low,
675 (unsigned long long) sconn->smb2.seqnum_range));
677 if (sconn->smb2.credits_granted < credit_charge) {
678 DEBUG(0, ("smb2_validate_message_id: client used more "
679 "credits than granted, mid %llu, charge %llu, "
680 "credits_granted %llu, "
681 "seqnum low/range: %llu/%llu\n",
682 (unsigned long long) message_id,
683 (unsigned long long) credit_charge,
684 (unsigned long long) sconn->smb2.credits_granted,
685 (unsigned long long) sconn->smb2.seqnum_low,
686 (unsigned long long) sconn->smb2.seqnum_range));
687 return false;
691 * now check the message ids
693 * for multi-credit requests we need to check all current mid plus
694 * the implicit mids caused by the credit charge
695 * e.g. current mid = 15, charge 5 => mark 15-19 as used
698 for (i = 0; i <= (credit_charge-1); i++) {
699 uint64_t id = message_id + i;
700 bool ok;
702 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
703 (unsigned long long)message_id,
704 credit_charge,
705 (unsigned long long)id));
707 ok = smb2_validate_sequence_number(sconn, message_id, id);
708 if (!ok) {
709 return false;
713 /* substract used credits */
714 sconn->smb2.credits_granted -= credit_charge;
716 return true;
719 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
721 int count;
722 int idx;
724 count = req->in.vector_count;
726 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
727 /* It's not a SMB2 request */
728 return NT_STATUS_INVALID_PARAMETER;
731 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
732 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
733 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
734 const uint8_t *inhdr = NULL;
736 if (hdr->iov_len != SMB2_HDR_BODY) {
737 return NT_STATUS_INVALID_PARAMETER;
740 if (body->iov_len < 2) {
741 return NT_STATUS_INVALID_PARAMETER;
744 inhdr = (const uint8_t *)hdr->iov_base;
746 /* Check the SMB2 header */
747 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
748 return NT_STATUS_INVALID_PARAMETER;
751 if (!smb2_validate_message_id(req->sconn, inhdr)) {
752 return NT_STATUS_INVALID_PARAMETER;
756 return NT_STATUS_OK;
759 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
760 const struct iovec *in_vector,
761 struct iovec *out_vector)
763 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
764 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
765 uint16_t credit_charge = 1;
766 uint16_t credits_requested;
767 uint32_t out_flags;
768 uint16_t cmd;
769 NTSTATUS out_status;
770 uint16_t credits_granted = 0;
771 uint64_t credits_possible;
772 uint16_t current_max_credits;
775 * first we grant only 1/16th of the max range.
777 * Windows also starts with the 1/16th and then grants
778 * more later. I was only able to trigger higher
779 * values, when using a very high credit charge.
781 * TODO: scale up depending on load, free memory
782 * or other stuff.
783 * Maybe also on the relationship between number
784 * of requests and the used sequence number.
785 * Which means we would grant more credits
786 * for client which use multi credit requests.
788 current_max_credits = sconn->smb2.max_credits / 16;
789 current_max_credits = MAX(current_max_credits, 1);
791 if (sconn->smb2.supports_multicredit) {
792 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
793 credit_charge = MAX(credit_charge, 1);
796 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
797 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
798 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
799 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
801 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
803 if (sconn->smb2.max_credits < credit_charge) {
804 smbd_server_connection_terminate(sconn,
805 "client error: credit charge > max credits\n");
806 return;
809 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
811 * In case we already send an async interim
812 * response, we should not grant
813 * credits on the final response.
815 credits_granted = 0;
816 } else if (credits_requested > 0) {
817 uint16_t additional_max = 0;
818 uint16_t additional_credits = credits_requested - 1;
820 switch (cmd) {
821 case SMB2_OP_NEGPROT:
822 break;
823 case SMB2_OP_SESSSETUP:
825 * Windows 2012 RC1 starts to grant
826 * additional credits
827 * with a successful session setup
829 if (NT_STATUS_IS_OK(out_status)) {
830 additional_max = 32;
832 break;
833 default:
835 * We match windows and only grant additional credits
836 * in chunks of 32.
838 additional_max = 32;
839 break;
842 additional_credits = MIN(additional_credits, additional_max);
844 credits_granted = credit_charge + additional_credits;
845 } else if (sconn->smb2.credits_granted == 0) {
847 * Make sure the client has always at least one credit
849 credits_granted = 1;
853 * sequence numbers should not wrap
855 * 1. calculate the possible credits until
856 * the sequence numbers start to wrap on 64-bit.
858 * 2. UINT64_MAX is used for Break Notifications.
860 * 2. truncate the possible credits to the maximum
861 * credits we want to grant to the client in total.
863 * 3. remove the range we'll already granted to the client
864 * this makes sure the client consumes the lowest sequence
865 * number, before we can grant additional credits.
867 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
868 if (credits_possible > 0) {
869 /* remove UINT64_MAX */
870 credits_possible -= 1;
872 credits_possible = MIN(credits_possible, current_max_credits);
873 credits_possible -= sconn->smb2.seqnum_range;
875 credits_granted = MIN(credits_granted, credits_possible);
877 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
878 sconn->smb2.credits_granted += credits_granted;
879 sconn->smb2.seqnum_range += credits_granted;
881 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
882 "granted %u, current possible/max %u/%u, "
883 "total granted/max/low/range %u/%u/%llu/%u\n",
884 (unsigned int)credits_requested,
885 (unsigned int)credit_charge,
886 (unsigned int)credits_granted,
887 (unsigned int)credits_possible,
888 (unsigned int)current_max_credits,
889 (unsigned int)sconn->smb2.credits_granted,
890 (unsigned int)sconn->smb2.max_credits,
891 (unsigned long long)sconn->smb2.seqnum_low,
892 (unsigned int)sconn->smb2.seqnum_range));
895 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
896 struct smbd_smb2_request *outreq)
898 int count, idx;
899 uint16_t total_credits = 0;
901 count = outreq->out.vector_count;
903 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
904 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
905 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
906 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
908 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
910 /* To match Windows, count up what we
911 just granted. */
912 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
913 /* Set to zero in all but the last reply. */
914 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
915 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
916 } else {
917 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
922 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
924 if (req->current_idx <= 1) {
925 if (size <= sizeof(req->out._body)) {
926 return data_blob_const(req->out._body, size);
930 return data_blob_talloc(req, NULL, size);
933 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
935 TALLOC_CTX *mem_ctx;
936 struct iovec *vector;
937 int count;
938 int idx;
940 count = req->in.vector_count;
941 if (count <= ARRAY_SIZE(req->out._vector)) {
942 mem_ctx = req;
943 vector = req->out._vector;
944 } else {
945 vector = talloc_zero_array(req, struct iovec, count);
946 if (vector == NULL) {
947 return NT_STATUS_NO_MEMORY;
949 mem_ctx = vector;
952 vector[0].iov_base = req->out.nbt_hdr;
953 vector[0].iov_len = 4;
954 SIVAL(req->out.nbt_hdr, 0, 0);
956 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
957 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
958 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
959 uint8_t *outhdr = NULL;
960 uint8_t *outbody = NULL;
961 uint32_t next_command_ofs = 0;
962 struct iovec *current = &vector[idx];
964 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
965 /* we have a next command -
966 * setup for the error case. */
967 next_command_ofs = SMB2_HDR_BODY + 9;
970 if (idx == 1) {
971 outhdr = req->out._hdr;
972 } else {
973 outhdr = talloc_zero_array(mem_ctx, uint8_t,
974 OUTVEC_ALLOC_SIZE);
975 if (outhdr == NULL) {
976 return NT_STATUS_NO_MEMORY;
980 outbody = outhdr + SMB2_HDR_BODY;
983 * SMBD_SMB2_TF_IOV_OFS might be used later
985 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
986 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
988 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
989 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
991 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
992 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
994 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
995 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
997 /* setup the SMB2 header */
998 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
999 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1000 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1001 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1002 SIVAL(outhdr, SMB2_HDR_STATUS,
1003 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1004 SSVAL(outhdr, SMB2_HDR_OPCODE,
1005 SVAL(inhdr, SMB2_HDR_OPCODE));
1006 SIVAL(outhdr, SMB2_HDR_FLAGS,
1007 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1008 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1009 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1010 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1011 SIVAL(outhdr, SMB2_HDR_PID,
1012 IVAL(inhdr, SMB2_HDR_PID));
1013 SIVAL(outhdr, SMB2_HDR_TID,
1014 IVAL(inhdr, SMB2_HDR_TID));
1015 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1016 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1017 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1018 inhdr + SMB2_HDR_SIGNATURE, 16);
1020 /* setup error body header */
1021 SSVAL(outbody, 0x00, 0x08 + 1);
1022 SSVAL(outbody, 0x02, 0);
1023 SIVAL(outbody, 0x04, 0);
1026 req->out.vector = vector;
1027 req->out.vector_count = count;
1029 /* setup the length of the NBT packet */
1030 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1032 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1034 return NT_STATUS_OK;
1037 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1038 const char *reason,
1039 const char *location)
1041 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1042 reason, location));
1043 exit_server_cleanly(reason);
1046 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1047 struct iovec *outvec,
1048 const struct iovec *srcvec)
1050 const uint8_t *srctf;
1051 size_t srctf_len;
1052 const uint8_t *srchdr;
1053 size_t srchdr_len;
1054 const uint8_t *srcbody;
1055 size_t srcbody_len;
1056 const uint8_t *expected_srcbody;
1057 const uint8_t *srcdyn;
1058 size_t srcdyn_len;
1059 const uint8_t *expected_srcdyn;
1060 uint8_t *dsttf;
1061 uint8_t *dsthdr;
1062 uint8_t *dstbody;
1063 uint8_t *dstdyn;
1065 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1066 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1067 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1068 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1069 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1070 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1071 expected_srcbody = srchdr + SMB2_HDR_BODY;
1072 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1073 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1074 expected_srcdyn = srcbody + 8;
1076 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1077 return false;
1080 if (srchdr_len != SMB2_HDR_BODY) {
1081 return false;
1084 if (srctf_len == SMB2_TF_HDR_SIZE) {
1085 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1086 if (dsttf == NULL) {
1087 return false;
1089 } else {
1090 dsttf = NULL;
1092 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1093 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1095 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1096 * be allocated with size OUTVEC_ALLOC_SIZE. */
1098 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1099 if (dsthdr == NULL) {
1100 return false;
1102 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1103 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1106 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1107 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1108 * then duplicate this. Else use talloc_memdup().
1111 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1112 dstbody = dsthdr + SMB2_HDR_BODY;
1113 } else {
1114 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1115 if (dstbody == NULL) {
1116 return false;
1119 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1120 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1123 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1124 * pointing to
1125 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1126 * then duplicate this. Else use talloc_memdup().
1129 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1130 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1131 } else if (srcdyn == NULL) {
1132 dstdyn = NULL;
1133 } else {
1134 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1135 if (dstdyn == NULL) {
1136 return false;
1139 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1140 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1142 return true;
1145 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1147 struct smbd_smb2_request *newreq = NULL;
1148 struct iovec *outvec = NULL;
1149 int count = req->out.vector_count;
1150 int i;
1152 newreq = smbd_smb2_request_allocate(req->sconn);
1153 if (!newreq) {
1154 return NULL;
1157 newreq->sconn = req->sconn;
1158 newreq->session = req->session;
1159 newreq->do_encryption = req->do_encryption;
1160 newreq->do_signing = req->do_signing;
1161 newreq->current_idx = req->current_idx;
1163 outvec = talloc_zero_array(newreq, struct iovec, count);
1164 if (!outvec) {
1165 TALLOC_FREE(newreq);
1166 return NULL;
1168 newreq->out.vector = outvec;
1169 newreq->out.vector_count = count;
1171 /* Setup the outvec's identically to req. */
1172 outvec[0].iov_base = newreq->out.nbt_hdr;
1173 outvec[0].iov_len = 4;
1174 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1176 /* Setup the vectors identically to the ones in req. */
1177 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1178 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1179 break;
1183 if (i < count) {
1184 /* Alloc failed. */
1185 TALLOC_FREE(newreq);
1186 return NULL;
1189 smb2_setup_nbt_length(newreq->out.vector,
1190 newreq->out.vector_count);
1192 return newreq;
1195 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1197 struct smbd_server_connection *sconn = req->sconn;
1198 struct smbXsrv_connection *conn = req->sconn->conn;
1199 int first_idx = 1;
1200 struct iovec *firsttf = NULL;
1201 struct iovec *outhdr_v = NULL;
1202 uint8_t *outhdr = NULL;
1203 struct smbd_smb2_request *nreq = NULL;
1204 NTSTATUS status;
1206 /* Create a new smb2 request we'll use
1207 for the interim return. */
1208 nreq = dup_smb2_req(req);
1209 if (!nreq) {
1210 return NT_STATUS_NO_MEMORY;
1213 /* Lose the last X out vectors. They're the
1214 ones we'll be using for the async reply. */
1215 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1217 smb2_setup_nbt_length(nreq->out.vector,
1218 nreq->out.vector_count);
1220 /* Step back to the previous reply. */
1221 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1222 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1223 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1224 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1225 /* And end the chain. */
1226 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1228 /* Calculate outgoing credits */
1229 smb2_calculate_credits(req, nreq);
1231 if (DEBUGLEVEL >= 10) {
1232 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1233 (unsigned int)nreq->current_idx );
1234 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1235 (unsigned int)nreq->out.vector_count );
1236 print_req_vectors(nreq);
1240 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1241 * we need to sign/encrypt here with the last/first key we remembered
1243 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1244 status = smb2_signing_encrypt_pdu(req->first_key,
1245 conn->protocol,
1246 firsttf,
1247 nreq->out.vector_count - first_idx);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 return status;
1251 } else if (req->last_key.length > 0) {
1252 status = smb2_signing_sign_pdu(req->last_key,
1253 conn->protocol,
1254 outhdr_v,
1255 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1261 nreq->queue_entry.mem_ctx = nreq;
1262 nreq->queue_entry.vector = nreq->out.vector;
1263 nreq->queue_entry.count = nreq->out.vector_count;
1264 DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1265 nreq->sconn->smb2.send_queue_len++;
1267 status = smbd_smb2_flush_send_queue(sconn);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 return status;
1272 return NT_STATUS_OK;
1275 struct smbd_smb2_request_pending_state {
1276 struct smbd_server_connection *sconn;
1277 struct smbd_smb2_send_queue queue_entry;
1278 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1279 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1282 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1283 struct tevent_timer *te,
1284 struct timeval current_time,
1285 void *private_data);
1287 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1288 struct tevent_req *subreq,
1289 uint32_t defer_time)
1291 NTSTATUS status;
1292 struct timeval defer_endtime;
1293 uint8_t *outhdr = NULL;
1294 uint32_t flags;
1296 if (!tevent_req_is_in_progress(subreq)) {
1298 * This is a performance optimization,
1299 * it avoids one tevent_loop iteration,
1300 * which means we avoid one
1301 * talloc_stackframe_pool/talloc_free pair.
1303 tevent_req_notify_callback(subreq);
1304 return NT_STATUS_OK;
1307 req->subreq = subreq;
1308 subreq = NULL;
1310 if (req->async_te) {
1311 /* We're already async. */
1312 return NT_STATUS_OK;
1315 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1316 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1317 if (flags & SMB2_HDR_FLAG_ASYNC) {
1318 /* We're already async. */
1319 return NT_STATUS_OK;
1322 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1324 * We're trying to go async in a compound
1325 * request chain.
1326 * This is only allowed for opens that
1327 * cause an oplock break, otherwise it
1328 * is not allowed. See [MS-SMB2].pdf
1329 * note <194> on Section 3.3.5.2.7.
1331 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1333 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1335 * Cancel the outstanding request.
1337 bool ok = tevent_req_cancel(req->subreq);
1338 if (ok) {
1339 return NT_STATUS_OK;
1341 TALLOC_FREE(req->subreq);
1342 return smbd_smb2_request_error(req,
1343 NT_STATUS_INTERNAL_ERROR);
1347 if (DEBUGLEVEL >= 10) {
1348 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1349 (unsigned int)req->current_idx );
1350 print_req_vectors(req);
1353 if (req->current_idx > 1) {
1355 * We're going async in a compound
1356 * chain after the first request has
1357 * already been processed. Send an
1358 * interim response containing the
1359 * set of replies already generated.
1361 int idx = req->current_idx;
1363 status = smb2_send_async_interim_response(req);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 return status;
1367 if (req->first_key.length > 0) {
1368 data_blob_clear_free(&req->first_key);
1371 req->current_idx = 1;
1374 * Re-arrange the in.vectors to remove what
1375 * we just sent.
1377 memmove(&req->in.vector[1],
1378 &req->in.vector[idx],
1379 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1380 req->in.vector_count = 1 + (req->in.vector_count - idx);
1382 /* Re-arrange the out.vectors to match. */
1383 memmove(&req->out.vector[1],
1384 &req->out.vector[idx],
1385 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1386 req->out.vector_count = 1 + (req->out.vector_count - idx);
1388 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1390 * We only have one remaining request as
1391 * we've processed everything else.
1392 * This is no longer a compound request.
1394 req->compound_related = false;
1395 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1396 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1397 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1400 if (req->last_key.length > 0) {
1401 data_blob_clear_free(&req->last_key);
1404 defer_endtime = timeval_current_ofs_usec(defer_time);
1405 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1406 req, defer_endtime,
1407 smbd_smb2_request_pending_timer,
1408 req);
1409 if (req->async_te == NULL) {
1410 return NT_STATUS_NO_MEMORY;
1413 return NT_STATUS_OK;
1416 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1417 struct tevent_timer *te,
1418 struct timeval current_time,
1419 void *private_data)
1421 struct smbd_smb2_request *req =
1422 talloc_get_type_abort(private_data,
1423 struct smbd_smb2_request);
1424 struct smbd_server_connection *sconn = req->sconn;
1425 struct smbd_smb2_request_pending_state *state = NULL;
1426 uint8_t *outhdr = NULL;
1427 const uint8_t *inhdr = NULL;
1428 uint8_t *tf = NULL;
1429 size_t tf_len = 0;
1430 uint8_t *hdr = NULL;
1431 uint8_t *body = NULL;
1432 uint8_t *dyn = NULL;
1433 uint32_t flags = 0;
1434 uint64_t session_id = 0;
1435 uint64_t message_id = 0;
1436 uint64_t nonce_high = 0;
1437 uint64_t nonce_low = 0;
1438 uint64_t async_id = 0;
1439 NTSTATUS status;
1441 TALLOC_FREE(req->async_te);
1443 /* Ensure our final reply matches the interim one. */
1444 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1445 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1446 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1447 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1448 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1450 async_id = message_id; /* keep it simple for now... */
1452 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1453 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1455 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1456 "going async\n",
1457 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1458 (unsigned long long)async_id ));
1461 * What we send is identical to a smbd_smb2_request_error
1462 * packet with an error status of STATUS_PENDING. Make use
1463 * of this fact sometime when refactoring. JRA.
1466 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1467 if (state == NULL) {
1468 smbd_server_connection_terminate(req->sconn,
1469 nt_errstr(NT_STATUS_NO_MEMORY));
1470 return;
1472 state->sconn = req->sconn;
1474 tf = state->buf + NBT_HDR_SIZE;
1475 tf_len = SMB2_TF_HDR_SIZE;
1477 hdr = tf + SMB2_TF_HDR_SIZE;
1478 body = hdr + SMB2_HDR_BODY;
1479 dyn = body + 8;
1481 if (req->do_encryption) {
1482 struct smbXsrv_session *x = req->session;
1484 nonce_high = x->nonce_high;
1485 nonce_low = x->nonce_low;
1487 x->nonce_low += 1;
1488 if (x->nonce_low == 0) {
1489 x->nonce_low += 1;
1490 x->nonce_high += 1;
1494 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1495 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1496 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1497 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1499 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1500 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1501 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1502 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1503 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1505 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1506 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1507 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1508 SBVAL(hdr, SMB2_HDR_PID, async_id);
1509 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1510 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1511 memcpy(hdr+SMB2_HDR_SIGNATURE,
1512 outhdr+SMB2_HDR_SIGNATURE, 16);
1514 SSVAL(body, 0x00, 0x08 + 1);
1516 SCVAL(body, 0x02, 0);
1517 SCVAL(body, 0x03, 0);
1518 SIVAL(body, 0x04, 0);
1519 /* Match W2K8R2... */
1520 SCVAL(dyn, 0x00, 0x21);
1522 state->vector[0].iov_base = (void *)state->buf;
1523 state->vector[0].iov_len = NBT_HDR_SIZE;
1525 if (req->do_encryption) {
1526 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1527 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1528 } else {
1529 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1530 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1533 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1534 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1536 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1537 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1539 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1540 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1542 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1544 /* Ensure we correctly go through crediting. Grant
1545 the credits now, and zero credits on the final
1546 response. */
1547 smb2_set_operation_credit(req->sconn,
1548 SMBD_SMB2_IN_HDR_IOV(req),
1549 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1551 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1553 if (DEBUGLVL(10)) {
1554 int i;
1556 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1557 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1558 (unsigned int)i,
1559 (unsigned int)ARRAY_SIZE(state->vector),
1560 (unsigned int)state->vector[i].iov_len);
1564 if (req->do_encryption) {
1565 struct smbXsrv_session *x = req->session;
1566 struct smbXsrv_connection *conn = x->connection;
1567 DATA_BLOB encryption_key = x->global->encryption_key;
1569 status = smb2_signing_encrypt_pdu(encryption_key,
1570 conn->protocol,
1571 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1572 SMBD_SMB2_NUM_IOV_PER_REQ);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 smbd_server_connection_terminate(req->sconn,
1575 nt_errstr(status));
1576 return;
1578 } else if (req->do_signing) {
1579 struct smbXsrv_session *x = req->session;
1580 struct smbXsrv_connection *conn = x->connection;
1581 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1583 status = smb2_signing_sign_pdu(signing_key,
1584 conn->protocol,
1585 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1586 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1587 if (!NT_STATUS_IS_OK(status)) {
1588 smbd_server_connection_terminate(req->sconn,
1589 nt_errstr(status));
1590 return;
1594 state->queue_entry.mem_ctx = state;
1595 state->queue_entry.vector = state->vector;
1596 state->queue_entry.count = ARRAY_SIZE(state->vector);
1597 DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1598 sconn->smb2.send_queue_len++;
1600 status = smbd_smb2_flush_send_queue(sconn);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 smbd_server_connection_terminate(sconn,
1603 nt_errstr(status));
1604 return;
1608 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1610 struct smbd_server_connection *sconn = req->sconn;
1611 struct smbd_smb2_request *cur;
1612 const uint8_t *inhdr;
1613 uint32_t flags;
1614 uint64_t search_message_id;
1615 uint64_t search_async_id;
1616 uint64_t found_id;
1618 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1620 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1621 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1622 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1625 * we don't need the request anymore
1626 * cancel requests never have a response
1628 DLIST_REMOVE(req->sconn->smb2.requests, req);
1629 TALLOC_FREE(req);
1631 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1632 const uint8_t *outhdr;
1633 uint64_t message_id;
1634 uint64_t async_id;
1636 if (cur->compound_related) {
1638 * Never cancel anything in a compound request.
1639 * Way too hard to deal with the result.
1641 continue;
1644 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1646 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1647 async_id = BVAL(outhdr, SMB2_HDR_PID);
1649 if (flags & SMB2_HDR_FLAG_ASYNC) {
1650 if (search_async_id == async_id) {
1651 found_id = async_id;
1652 break;
1654 } else {
1655 if (search_message_id == message_id) {
1656 found_id = message_id;
1657 break;
1662 if (cur && cur->subreq) {
1663 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1664 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1665 "cancel opcode[%s] mid %llu\n",
1666 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1667 (unsigned long long)found_id ));
1668 tevent_req_cancel(cur->subreq);
1671 return NT_STATUS_OK;
1674 /*************************************************************
1675 Ensure an incoming tid is a valid one for us to access.
1676 Change to the associated uid credentials and chdir to the
1677 valid tid directory.
1678 *************************************************************/
1680 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1682 const uint8_t *inhdr;
1683 uint32_t in_flags;
1684 uint32_t in_tid;
1685 struct smbXsrv_tcon *tcon;
1686 NTSTATUS status;
1687 NTTIME now = timeval_to_nttime(&req->request_time);
1689 req->tcon = NULL;
1691 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1693 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1694 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1696 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1697 in_tid = req->last_tid;
1700 req->last_tid = 0;
1702 status = smb2srv_tcon_lookup(req->session,
1703 in_tid, now, &tcon);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 return status;
1708 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1709 return NT_STATUS_ACCESS_DENIED;
1712 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1713 if (!set_current_service(tcon->compat, 0, true)) {
1714 return NT_STATUS_ACCESS_DENIED;
1717 req->tcon = tcon;
1718 req->last_tid = in_tid;
1720 return NT_STATUS_OK;
1723 /*************************************************************
1724 Ensure an incoming session_id is a valid one for us to access.
1725 *************************************************************/
1727 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1729 const uint8_t *inhdr;
1730 uint32_t in_flags;
1731 uint16_t in_opcode;
1732 uint64_t in_session_id;
1733 struct smbXsrv_session *session = NULL;
1734 struct auth_session_info *session_info;
1735 NTSTATUS status;
1736 NTTIME now = timeval_to_nttime(&req->request_time);
1738 req->session = NULL;
1739 req->tcon = NULL;
1741 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1743 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1744 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1745 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1747 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1748 in_session_id = req->last_session_id;
1751 req->last_session_id = 0;
1753 /* lookup an existing session */
1754 status = smb2srv_session_lookup(req->sconn->conn,
1755 in_session_id, now,
1756 &session);
1757 if (session) {
1758 req->session = session;
1759 req->last_session_id = in_session_id;
1761 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1762 switch (in_opcode) {
1763 case SMB2_OP_SESSSETUP:
1764 status = NT_STATUS_OK;
1765 break;
1766 default:
1767 break;
1770 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1771 switch (in_opcode) {
1772 case SMB2_OP_TCON:
1773 case SMB2_OP_CREATE:
1774 case SMB2_OP_GETINFO:
1775 case SMB2_OP_SETINFO:
1776 return NT_STATUS_INVALID_HANDLE;
1777 default:
1779 * Notice the check for
1780 * (session_info == NULL)
1781 * below.
1783 status = NT_STATUS_OK;
1784 break;
1787 if (!NT_STATUS_IS_OK(status)) {
1788 return status;
1791 session_info = session->global->auth_session_info;
1792 if (session_info == NULL) {
1793 return NT_STATUS_INVALID_HANDLE;
1796 if (in_session_id != req->sconn->conn->last_session_id) {
1797 req->sconn->conn->last_session_id = in_session_id;
1798 set_current_user_info(session_info->unix_info->sanitized_username,
1799 session_info->unix_info->unix_name,
1800 session_info->info->domain_name);
1803 return NT_STATUS_OK;
1806 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1807 uint32_t data_length)
1809 uint16_t needed_charge;
1810 uint16_t credit_charge = 1;
1811 const uint8_t *inhdr;
1813 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1815 if (req->sconn->smb2.supports_multicredit) {
1816 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1817 credit_charge = MAX(credit_charge, 1);
1820 needed_charge = (data_length - 1)/ 65536 + 1;
1822 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1823 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1824 credit_charge, needed_charge));
1826 if (needed_charge > credit_charge) {
1827 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1828 credit_charge, needed_charge));
1829 return NT_STATUS_INVALID_PARAMETER;
1832 return NT_STATUS_OK;
1835 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1836 size_t expected_body_size)
1838 struct iovec *inhdr_v;
1839 const uint8_t *inhdr;
1840 uint16_t opcode;
1841 const uint8_t *inbody;
1842 size_t body_size;
1843 size_t min_dyn_size = expected_body_size & 0x00000001;
1844 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1847 * The following should be checked already.
1849 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1850 return NT_STATUS_INTERNAL_ERROR;
1852 if (req->current_idx > max_idx) {
1853 return NT_STATUS_INTERNAL_ERROR;
1856 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1857 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1858 return NT_STATUS_INTERNAL_ERROR;
1860 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1861 return NT_STATUS_INTERNAL_ERROR;
1864 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1865 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1867 switch (opcode) {
1868 case SMB2_OP_IOCTL:
1869 case SMB2_OP_GETINFO:
1870 min_dyn_size = 0;
1871 break;
1872 case SMB2_OP_WRITE:
1873 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1874 if (req->smb1req->unread_bytes < min_dyn_size) {
1875 return NT_STATUS_INVALID_PARAMETER;
1878 min_dyn_size = 0;
1880 break;
1884 * Now check the expected body size,
1885 * where the last byte might be in the
1886 * dynamic section..
1888 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1889 return NT_STATUS_INVALID_PARAMETER;
1891 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1892 return NT_STATUS_INVALID_PARAMETER;
1895 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1897 body_size = SVAL(inbody, 0x00);
1898 if (body_size != expected_body_size) {
1899 return NT_STATUS_INVALID_PARAMETER;
1902 return NT_STATUS_OK;
1905 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1907 struct smbXsrv_connection *conn = req->sconn->conn;
1908 const struct smbd_smb2_dispatch_table *call = NULL;
1909 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1910 const uint8_t *inhdr;
1911 uint16_t opcode;
1912 uint32_t flags;
1913 uint64_t mid;
1914 NTSTATUS status;
1915 NTSTATUS session_status;
1916 uint32_t allowed_flags;
1917 NTSTATUS return_value;
1918 struct smbXsrv_session *x = NULL;
1919 bool signing_required = false;
1920 bool encryption_required = false;
1922 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1924 /* TODO: verify more things */
1926 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1927 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1928 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1929 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1930 smb2_opcode_name(opcode),
1931 (unsigned long long)mid));
1933 if (conn->protocol >= PROTOCOL_SMB2_02) {
1935 * once the protocol is negotiated
1936 * SMB2_OP_NEGPROT is not allowed anymore
1938 if (opcode == SMB2_OP_NEGPROT) {
1939 /* drop the connection */
1940 return NT_STATUS_INVALID_PARAMETER;
1942 } else {
1944 * if the protocol is not negotiated yet
1945 * only SMB2_OP_NEGPROT is allowed.
1947 if (opcode != SMB2_OP_NEGPROT) {
1948 /* drop the connection */
1949 return NT_STATUS_INVALID_PARAMETER;
1954 * Check if the client provided a valid session id,
1955 * if so smbd_smb2_request_check_session() calls
1956 * set_current_user_info().
1958 * As some command don't require a valid session id
1959 * we defer the check of the session_status
1961 session_status = smbd_smb2_request_check_session(req);
1962 x = req->session;
1963 if (x != NULL) {
1964 signing_required = x->global->signing_required;
1965 encryption_required = x->global->encryption_required;
1967 if (opcode == SMB2_OP_SESSSETUP &&
1968 x->global->channels[0].signing_key.length) {
1969 signing_required = true;
1973 req->do_signing = false;
1974 req->do_encryption = false;
1975 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1976 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1977 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1979 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1980 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1981 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1982 (unsigned long long)x->global->session_wire_id,
1983 (unsigned long long)tf_session_id));
1985 * TODO: windows allows this...
1986 * should we drop the connection?
1988 * For now we just return ACCESS_DENIED
1989 * (Windows clients never trigger this)
1990 * and wait for an update of [MS-SMB2].
1992 return smbd_smb2_request_error(req,
1993 NT_STATUS_ACCESS_DENIED);
1996 req->do_encryption = true;
1999 if (encryption_required && !req->do_encryption) {
2000 return smbd_smb2_request_error(req,
2001 NT_STATUS_ACCESS_DENIED);
2004 call = smbd_smb2_call(opcode);
2005 if (call == NULL) {
2006 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2009 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2010 SMB2_HDR_FLAG_SIGNED |
2011 SMB2_HDR_FLAG_DFS;
2012 if (opcode == SMB2_OP_CANCEL) {
2013 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2015 if ((flags & ~allowed_flags) != 0) {
2016 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2019 if (flags & SMB2_HDR_FLAG_CHAINED) {
2021 * This check is mostly for giving the correct error code
2022 * for compounded requests.
2024 if (!NT_STATUS_IS_OK(session_status)) {
2025 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2027 } else {
2028 req->compat_chain_fsp = NULL;
2031 if (req->do_encryption) {
2032 signing_required = false;
2033 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2034 DATA_BLOB signing_key;
2036 if (x == NULL) {
2037 return smbd_smb2_request_error(
2038 req, NT_STATUS_USER_SESSION_DELETED);
2041 signing_key = x->global->channels[0].signing_key;
2044 * If we have a signing key, we should
2045 * sign the response
2047 if (signing_key.length > 0) {
2048 req->do_signing = true;
2051 status = smb2_signing_check_pdu(signing_key,
2052 conn->protocol,
2053 SMBD_SMB2_IN_HDR_IOV(req),
2054 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2055 if (!NT_STATUS_IS_OK(status)) {
2056 return smbd_smb2_request_error(req, status);
2060 * Now that we know the request was correctly signed
2061 * we have to sign the response too.
2063 req->do_signing = true;
2065 if (!NT_STATUS_IS_OK(session_status)) {
2066 return smbd_smb2_request_error(req, session_status);
2068 } else if (opcode == SMB2_OP_CANCEL) {
2069 /* Cancel requests are allowed to skip the signing */
2070 } else if (signing_required) {
2072 * If signing is required we try to sign
2073 * a possible error response
2075 req->do_signing = true;
2076 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2079 if (flags & SMB2_HDR_FLAG_CHAINED) {
2080 req->compound_related = true;
2083 if (call->need_session) {
2084 if (!NT_STATUS_IS_OK(session_status)) {
2085 return smbd_smb2_request_error(req, session_status);
2089 if (call->need_tcon) {
2090 SMB_ASSERT(call->need_session);
2093 * This call needs to be run as user.
2095 * smbd_smb2_request_check_tcon()
2096 * calls change_to_user() on success.
2098 status = smbd_smb2_request_check_tcon(req);
2099 if (!NT_STATUS_IS_OK(status)) {
2100 return smbd_smb2_request_error(req, status);
2102 if (req->tcon->global->encryption_required) {
2103 encryption_required = true;
2105 if (encryption_required && !req->do_encryption) {
2106 return smbd_smb2_request_error(req,
2107 NT_STATUS_ACCESS_DENIED);
2111 if (call->fileid_ofs != 0) {
2112 size_t needed = call->fileid_ofs + 16;
2113 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2114 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2115 uint64_t file_id_persistent;
2116 uint64_t file_id_volatile;
2117 struct files_struct *fsp;
2119 SMB_ASSERT(call->need_tcon);
2121 if (needed > body_size) {
2122 return smbd_smb2_request_error(req,
2123 NT_STATUS_INVALID_PARAMETER);
2126 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2127 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2129 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2130 if (fsp == NULL) {
2131 if (!call->allow_invalid_fileid) {
2132 return smbd_smb2_request_error(req,
2133 NT_STATUS_FILE_CLOSED);
2136 if (file_id_persistent != UINT64_MAX) {
2137 return smbd_smb2_request_error(req,
2138 NT_STATUS_FILE_CLOSED);
2140 if (file_id_volatile != UINT64_MAX) {
2141 return smbd_smb2_request_error(req,
2142 NT_STATUS_FILE_CLOSED);
2147 if (call->as_root) {
2148 SMB_ASSERT(call->fileid_ofs == 0);
2149 /* This call needs to be run as root */
2150 change_to_root_user();
2151 } else {
2152 SMB_ASSERT(call->need_tcon);
2155 switch (opcode) {
2156 case SMB2_OP_NEGPROT:
2158 START_PROFILE(smb2_negprot);
2159 return_value = smbd_smb2_request_process_negprot(req);
2160 END_PROFILE(smb2_negprot);
2162 break;
2164 case SMB2_OP_SESSSETUP:
2166 START_PROFILE(smb2_sesssetup);
2167 return_value = smbd_smb2_request_process_sesssetup(req);
2168 END_PROFILE(smb2_sesssetup);
2170 break;
2172 case SMB2_OP_LOGOFF:
2174 START_PROFILE(smb2_logoff);
2175 return_value = smbd_smb2_request_process_logoff(req);
2176 END_PROFILE(smb2_logoff);
2178 break;
2180 case SMB2_OP_TCON:
2182 START_PROFILE(smb2_tcon);
2183 return_value = smbd_smb2_request_process_tcon(req);
2184 END_PROFILE(smb2_tcon);
2186 break;
2188 case SMB2_OP_TDIS:
2190 START_PROFILE(smb2_tdis);
2191 return_value = smbd_smb2_request_process_tdis(req);
2192 END_PROFILE(smb2_tdis);
2194 break;
2196 case SMB2_OP_CREATE:
2198 START_PROFILE(smb2_create);
2199 return_value = smbd_smb2_request_process_create(req);
2200 END_PROFILE(smb2_create);
2202 break;
2204 case SMB2_OP_CLOSE:
2206 START_PROFILE(smb2_close);
2207 return_value = smbd_smb2_request_process_close(req);
2208 END_PROFILE(smb2_close);
2210 break;
2212 case SMB2_OP_FLUSH:
2214 START_PROFILE(smb2_flush);
2215 return_value = smbd_smb2_request_process_flush(req);
2216 END_PROFILE(smb2_flush);
2218 break;
2220 case SMB2_OP_READ:
2222 START_PROFILE(smb2_read);
2223 return_value = smbd_smb2_request_process_read(req);
2224 END_PROFILE(smb2_read);
2226 break;
2228 case SMB2_OP_WRITE:
2230 START_PROFILE(smb2_write);
2231 return_value = smbd_smb2_request_process_write(req);
2232 END_PROFILE(smb2_write);
2234 break;
2236 case SMB2_OP_LOCK:
2238 START_PROFILE(smb2_lock);
2239 return_value = smbd_smb2_request_process_lock(req);
2240 END_PROFILE(smb2_lock);
2242 break;
2244 case SMB2_OP_IOCTL:
2246 START_PROFILE(smb2_ioctl);
2247 return_value = smbd_smb2_request_process_ioctl(req);
2248 END_PROFILE(smb2_ioctl);
2250 break;
2252 case SMB2_OP_CANCEL:
2254 START_PROFILE(smb2_cancel);
2255 return_value = smbd_smb2_request_process_cancel(req);
2256 END_PROFILE(smb2_cancel);
2258 break;
2260 case SMB2_OP_KEEPALIVE:
2262 START_PROFILE(smb2_keepalive);
2263 return_value = smbd_smb2_request_process_keepalive(req);
2264 END_PROFILE(smb2_keepalive);
2266 break;
2268 case SMB2_OP_FIND:
2270 START_PROFILE(smb2_find);
2271 return_value = smbd_smb2_request_process_find(req);
2272 END_PROFILE(smb2_find);
2274 break;
2276 case SMB2_OP_NOTIFY:
2278 START_PROFILE(smb2_notify);
2279 return_value = smbd_smb2_request_process_notify(req);
2280 END_PROFILE(smb2_notify);
2282 break;
2284 case SMB2_OP_GETINFO:
2286 START_PROFILE(smb2_getinfo);
2287 return_value = smbd_smb2_request_process_getinfo(req);
2288 END_PROFILE(smb2_getinfo);
2290 break;
2292 case SMB2_OP_SETINFO:
2294 START_PROFILE(smb2_setinfo);
2295 return_value = smbd_smb2_request_process_setinfo(req);
2296 END_PROFILE(smb2_setinfo);
2298 break;
2300 case SMB2_OP_BREAK:
2302 START_PROFILE(smb2_break);
2303 return_value = smbd_smb2_request_process_break(req);
2304 END_PROFILE(smb2_break);
2306 break;
2308 default:
2309 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2310 break;
2312 return return_value;
2315 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2317 struct smbd_server_connection *sconn = req->sconn;
2318 struct smbXsrv_connection *conn = req->sconn->conn;
2319 int first_idx = 1;
2320 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2321 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2322 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2323 NTSTATUS status;
2325 req->subreq = NULL;
2326 TALLOC_FREE(req->async_te);
2328 if (req->do_encryption &&
2329 (firsttf->iov_len == 0) &&
2330 (req->first_key.length == 0) &&
2331 (req->session != NULL) &&
2332 (req->session->global->encryption_key.length != 0))
2334 DATA_BLOB encryption_key = req->session->global->encryption_key;
2335 uint8_t *tf;
2336 uint64_t session_id = req->session->global->session_wire_id;
2337 struct smbXsrv_session *x = req->session;
2338 uint64_t nonce_high;
2339 uint64_t nonce_low;
2341 nonce_high = x->nonce_high;
2342 nonce_low = x->nonce_low;
2344 x->nonce_low += 1;
2345 if (x->nonce_low == 0) {
2346 x->nonce_low += 1;
2347 x->nonce_high += 1;
2351 * We need to place the SMB2_TRANSFORM header before the
2352 * first SMB2 header
2356 * we need to remember the encryption key
2357 * and defer the signing/encryption until
2358 * we are sure that we do not change
2359 * the header again.
2361 req->first_key = data_blob_dup_talloc(req, encryption_key);
2362 if (req->first_key.data == NULL) {
2363 return NT_STATUS_NO_MEMORY;
2366 tf = talloc_zero_array(req, uint8_t,
2367 SMB2_TF_HDR_SIZE);
2368 if (tf == NULL) {
2369 return NT_STATUS_NO_MEMORY;
2372 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2373 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2374 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2375 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2377 firsttf->iov_base = (void *)tf;
2378 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2381 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2382 (req->last_key.length > 0) &&
2383 (firsttf->iov_len == 0))
2385 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2386 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2389 * As we are sure the header of the last request in the
2390 * compound chain will not change, we can to sign here
2391 * with the last signing key we remembered.
2393 status = smb2_signing_sign_pdu(req->last_key,
2394 conn->protocol,
2395 lasthdr,
2396 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 return status;
2401 if (req->last_key.length > 0) {
2402 data_blob_clear_free(&req->last_key);
2405 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2407 if (req->current_idx < req->out.vector_count) {
2409 * We must process the remaining compound
2410 * SMB2 requests before any new incoming SMB2
2411 * requests. This is because incoming SMB2
2412 * requests may include a cancel for a
2413 * compound request we haven't processed
2414 * yet.
2416 struct tevent_immediate *im = tevent_create_immediate(req);
2417 if (!im) {
2418 return NT_STATUS_NO_MEMORY;
2421 if (req->do_signing && firsttf->iov_len == 0) {
2422 struct smbXsrv_session *x = req->session;
2423 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2426 * we need to remember the signing key
2427 * and defer the signing until
2428 * we are sure that we do not change
2429 * the header again.
2431 req->last_key = data_blob_dup_talloc(req, signing_key);
2432 if (req->last_key.data == NULL) {
2433 return NT_STATUS_NO_MEMORY;
2437 tevent_schedule_immediate(im,
2438 req->sconn->ev_ctx,
2439 smbd_smb2_request_dispatch_immediate,
2440 req);
2441 return NT_STATUS_OK;
2444 if (req->compound_related) {
2445 req->compound_related = false;
2448 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2450 /* Set credit for these operations (zero credits if this
2451 is a final reply for an async operation). */
2452 smb2_calculate_credits(req, req);
2455 * now check if we need to sign the current response
2457 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2458 status = smb2_signing_encrypt_pdu(req->first_key,
2459 conn->protocol,
2460 firsttf,
2461 req->out.vector_count - first_idx);
2462 if (!NT_STATUS_IS_OK(status)) {
2463 return status;
2465 } else if (req->do_signing) {
2466 struct smbXsrv_session *x = req->session;
2467 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2469 status = smb2_signing_sign_pdu(signing_key,
2470 conn->protocol,
2471 outhdr,
2472 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 return status;
2477 if (req->first_key.length > 0) {
2478 data_blob_clear_free(&req->first_key);
2481 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2482 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2483 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2484 /* Dynamic part is NULL. Chop it off,
2485 We're going to send it via sendfile. */
2486 req->out.vector_count -= 1;
2490 * We're done with this request -
2491 * move it off the "being processed" queue.
2493 DLIST_REMOVE(req->sconn->smb2.requests, req);
2495 req->queue_entry.mem_ctx = req;
2496 req->queue_entry.vector = req->out.vector;
2497 req->queue_entry.count = req->out.vector_count;
2498 DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2499 req->sconn->smb2.send_queue_len++;
2501 status = smbd_smb2_flush_send_queue(sconn);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 return status;
2506 return NT_STATUS_OK;
2509 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2511 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2512 struct tevent_immediate *im,
2513 void *private_data)
2515 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2516 struct smbd_smb2_request);
2517 struct smbd_server_connection *sconn = req->sconn;
2518 NTSTATUS status;
2520 TALLOC_FREE(im);
2522 if (DEBUGLEVEL >= 10) {
2523 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2524 req->current_idx, req->in.vector_count));
2525 print_req_vectors(req);
2528 status = smbd_smb2_request_dispatch(req);
2529 if (!NT_STATUS_IS_OK(status)) {
2530 smbd_server_connection_terminate(sconn, nt_errstr(status));
2531 return;
2534 status = smbd_smb2_request_next_incoming(sconn);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 smbd_server_connection_terminate(sconn, nt_errstr(status));
2537 return;
2541 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2542 NTSTATUS status,
2543 DATA_BLOB body, DATA_BLOB *dyn,
2544 const char *location)
2546 uint8_t *outhdr;
2547 struct iovec *outbody_v;
2548 struct iovec *outdyn_v;
2549 uint32_t next_command_ofs;
2551 DEBUG(10,("smbd_smb2_request_done_ex: "
2552 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2553 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2554 dyn ? "yes": "no",
2555 (unsigned int)(dyn ? dyn->length : 0),
2556 location));
2558 if (body.length < 2) {
2559 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2562 if ((body.length % 2) != 0) {
2563 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2566 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2567 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2568 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2570 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2571 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2573 outbody_v->iov_base = (void *)body.data;
2574 outbody_v->iov_len = body.length;
2576 if (dyn) {
2577 outdyn_v->iov_base = (void *)dyn->data;
2578 outdyn_v->iov_len = dyn->length;
2579 } else {
2580 outdyn_v->iov_base = NULL;
2581 outdyn_v->iov_len = 0;
2584 /* see if we need to recalculate the offset to the next response */
2585 if (next_command_ofs > 0) {
2586 next_command_ofs = SMB2_HDR_BODY;
2587 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2588 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2591 if ((next_command_ofs % 8) != 0) {
2592 size_t pad_size = 8 - (next_command_ofs % 8);
2593 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2595 * if the dyn buffer is empty
2596 * we can use it to add padding
2598 uint8_t *pad;
2600 pad = talloc_zero_array(req,
2601 uint8_t, pad_size);
2602 if (pad == NULL) {
2603 return smbd_smb2_request_error(req,
2604 NT_STATUS_NO_MEMORY);
2607 outdyn_v->iov_base = (void *)pad;
2608 outdyn_v->iov_len = pad_size;
2609 } else {
2611 * For now we copy the dynamic buffer
2612 * and add the padding to the new buffer
2614 size_t old_size;
2615 uint8_t *old_dyn;
2616 size_t new_size;
2617 uint8_t *new_dyn;
2619 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2620 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2622 new_size = old_size + pad_size;
2623 new_dyn = talloc_zero_array(req,
2624 uint8_t, new_size);
2625 if (new_dyn == NULL) {
2626 return smbd_smb2_request_error(req,
2627 NT_STATUS_NO_MEMORY);
2630 memcpy(new_dyn, old_dyn, old_size);
2631 memset(new_dyn + old_size, 0, pad_size);
2633 outdyn_v->iov_base = (void *)new_dyn;
2634 outdyn_v->iov_len = new_size;
2636 next_command_ofs += pad_size;
2639 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2641 return smbd_smb2_request_reply(req);
2644 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2645 NTSTATUS status,
2646 DATA_BLOB *info,
2647 const char *location)
2649 DATA_BLOB body;
2650 DATA_BLOB _dyn;
2651 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2652 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2654 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2655 req->current_idx, nt_errstr(status), info ? " +info" : "",
2656 location));
2658 if (unread_bytes) {
2659 /* Recvfile error. Drain incoming socket. */
2660 size_t ret;
2662 errno = 0;
2663 ret = drain_socket(req->sconn->sock, unread_bytes);
2664 if (ret != unread_bytes) {
2665 NTSTATUS error;
2667 if (errno == 0) {
2668 error = NT_STATUS_IO_DEVICE_ERROR;
2669 } else {
2670 error = map_nt_error_from_unix_common(errno);
2673 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2674 "ret[%u] errno[%d] => %s\n",
2675 (unsigned)unread_bytes,
2676 (unsigned)ret, errno, nt_errstr(error)));
2677 return error;
2681 body.data = outhdr + SMB2_HDR_BODY;
2682 body.length = 8;
2683 SSVAL(body.data, 0, 9);
2685 if (info) {
2686 SIVAL(body.data, 0x04, info->length);
2687 } else {
2688 /* Allocated size of req->out.vector[i].iov_base
2689 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2690 * 1 byte without having to do an alloc.
2692 info = &_dyn;
2693 info->data = ((uint8_t *)outhdr) +
2694 OUTVEC_ALLOC_SIZE - 1;
2695 info->length = 1;
2696 SCVAL(info->data, 0, 0);
2700 * Note: Even if there is an error, continue to process the request.
2701 * per MS-SMB2.
2704 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2708 struct smbd_smb2_send_oplock_break_state {
2709 struct smbd_server_connection *sconn;
2710 struct smbd_smb2_send_queue queue_entry;
2711 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2712 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2715 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2716 struct smbXsrv_session *session,
2717 struct smbXsrv_tcon *tcon,
2718 struct smbXsrv_open *op,
2719 uint8_t oplock_level)
2721 struct smbd_smb2_send_oplock_break_state *state;
2722 struct smbXsrv_connection *conn = sconn->conn;
2723 uint8_t *tf;
2724 size_t tf_len;
2725 uint8_t *hdr;
2726 uint8_t *body;
2727 size_t body_len;
2728 uint8_t *dyn;
2729 size_t dyn_len;
2730 bool do_encryption = session->global->encryption_required;
2731 uint64_t nonce_high = 0;
2732 uint64_t nonce_low = 0;
2733 NTSTATUS status;
2735 if (tcon->global->encryption_required) {
2736 do_encryption = true;
2739 state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2740 if (state == NULL) {
2741 return NT_STATUS_NO_MEMORY;
2743 state->sconn = sconn;
2745 tf = state->buf + NBT_HDR_SIZE;
2746 tf_len = SMB2_TF_HDR_SIZE;
2747 hdr = tf + tf_len;
2748 body = hdr + SMB2_HDR_BODY;
2749 body_len = 0x18;
2750 dyn = body + body_len;
2751 dyn_len = 0;
2753 if (do_encryption) {
2754 nonce_high = session->nonce_high;
2755 nonce_low = session->nonce_low;
2757 session->nonce_low += 1;
2758 if (session->nonce_low == 0) {
2759 session->nonce_low += 1;
2760 session->nonce_high += 1;
2764 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2765 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2766 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2767 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2769 SIVAL(hdr, 0, SMB2_MAGIC);
2770 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2771 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2772 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2773 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2774 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2775 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2776 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2777 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2778 SIVAL(hdr, SMB2_HDR_PID, 0);
2779 SIVAL(hdr, SMB2_HDR_TID, 0);
2780 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2781 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2783 SSVAL(body, 0x00, body_len);
2785 SCVAL(body, 0x02, oplock_level);
2786 SCVAL(body, 0x03, 0); /* reserved */
2787 SIVAL(body, 0x04, 0); /* reserved */
2788 SBVAL(body, 0x08, op->global->open_persistent_id);
2789 SBVAL(body, 0x10, op->global->open_volatile_id);
2791 state->vector[0].iov_base = (void *)state->buf;
2792 state->vector[0].iov_len = NBT_HDR_SIZE;
2794 if (do_encryption) {
2795 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2796 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2797 } else {
2798 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2799 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2802 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2803 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2805 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2806 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2808 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2809 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2811 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2813 if (do_encryption) {
2814 DATA_BLOB encryption_key = session->global->encryption_key;
2816 status = smb2_signing_encrypt_pdu(encryption_key,
2817 conn->protocol,
2818 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2819 SMBD_SMB2_NUM_IOV_PER_REQ);
2820 if (!NT_STATUS_IS_OK(status)) {
2821 return status;
2825 state->queue_entry.mem_ctx = state;
2826 state->queue_entry.vector = state->vector;
2827 state->queue_entry.count = ARRAY_SIZE(state->vector);
2828 DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2829 state->sconn->smb2.send_queue_len++;
2831 status = smbd_smb2_flush_send_queue(sconn);
2832 if (!NT_STATUS_IS_OK(status)) {
2833 return status;
2836 return NT_STATUS_OK;
2839 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2841 NTSTATUS status;
2842 uint32_t flags;
2843 uint64_t file_id_persistent;
2844 uint64_t file_id_volatile;
2845 struct smbXsrv_open *op = NULL;
2846 struct files_struct *fsp = NULL;
2847 const uint8_t *body = NULL;
2850 * This is only called with a pktbuf
2851 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2852 * bytes
2855 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2856 /* Transform header. Cannot recvfile. */
2857 return false;
2859 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2860 /* Not SMB2. Normal error path will cope. */
2861 return false;
2863 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2864 /* Not SMB2. Normal error path will cope. */
2865 return false;
2867 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2868 /* Needs to be a WRITE. */
2869 return false;
2871 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2872 /* Chained. Cannot recvfile. */
2873 return false;
2875 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2876 if (flags & SMB2_HDR_FLAG_CHAINED) {
2877 /* Chained. Cannot recvfile. */
2878 return false;
2880 if (flags & SMB2_HDR_FLAG_SIGNED) {
2881 /* Signed. Cannot recvfile. */
2882 return false;
2885 body = &state->pktbuf[SMB2_HDR_BODY];
2887 file_id_persistent = BVAL(body, 0x10);
2888 file_id_volatile = BVAL(body, 0x18);
2890 status = smb2srv_open_lookup(state->req->sconn->conn,
2891 file_id_persistent,
2892 file_id_volatile,
2893 0, /* now */
2894 &op);
2895 if (!NT_STATUS_IS_OK(status)) {
2896 return false;
2899 fsp = op->compat;
2900 if (fsp == NULL) {
2901 return false;
2903 if (fsp->conn == NULL) {
2904 return false;
2907 if (IS_IPC(fsp->conn)) {
2908 return false;
2910 if (IS_PRINT(fsp->conn)) {
2911 return false;
2914 DEBUG(10,("Doing recvfile write len = %u\n",
2915 (unsigned int)(state->pktfull - state->pktlen)));
2917 return true;
2920 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2922 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2923 size_t max_send_queue_len;
2924 size_t cur_send_queue_len;
2926 if (!NT_STATUS_IS_OK(sconn->status)) {
2928 * we're not supposed to do any io
2930 return NT_STATUS_OK;
2933 if (state->req != NULL) {
2935 * if there is already a tstream_readv_pdu
2936 * pending, we are done.
2938 return NT_STATUS_OK;
2941 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2942 cur_send_queue_len = sconn->smb2.send_queue_len;
2944 if (cur_send_queue_len > max_send_queue_len) {
2946 * if we have a lot of requests to send,
2947 * we wait until they are on the wire until we
2948 * ask for the next request.
2950 return NT_STATUS_OK;
2953 /* ask for the next request */
2954 ZERO_STRUCTP(state);
2955 state->req = smbd_smb2_request_allocate(sconn);
2956 if (state->req == NULL) {
2957 return NT_STATUS_NO_MEMORY;
2959 state->req->sconn = sconn;
2960 state->min_recv_size = lp_min_receive_file_size();
2962 TEVENT_FD_READABLE(sconn->smb2.fde);
2964 return NT_STATUS_OK;
2967 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2968 uint8_t *inbuf, size_t size)
2970 NTSTATUS status;
2971 struct smbd_smb2_request *req = NULL;
2973 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2974 (unsigned int)size));
2976 status = smbd_initialize_smb2(sconn);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 smbd_server_connection_terminate(sconn, nt_errstr(status));
2979 return;
2982 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
2983 if (!NT_STATUS_IS_OK(status)) {
2984 smbd_server_connection_terminate(sconn, nt_errstr(status));
2985 return;
2988 status = smbd_smb2_request_validate(req);
2989 if (!NT_STATUS_IS_OK(status)) {
2990 smbd_server_connection_terminate(sconn, nt_errstr(status));
2991 return;
2994 status = smbd_smb2_request_setup_out(req);
2995 if (!NT_STATUS_IS_OK(status)) {
2996 smbd_server_connection_terminate(sconn, nt_errstr(status));
2997 return;
3000 status = smbd_smb2_request_dispatch(req);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 smbd_server_connection_terminate(sconn, nt_errstr(status));
3003 return;
3006 status = smbd_smb2_request_next_incoming(sconn);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 smbd_server_connection_terminate(sconn, nt_errstr(status));
3009 return;
3012 sconn->num_requests++;
3015 static int socket_error_from_errno(int ret,
3016 int sys_errno,
3017 bool *retry)
3019 *retry = false;
3021 if (ret >= 0) {
3022 return 0;
3025 if (ret != -1) {
3026 return EIO;
3029 if (sys_errno == 0) {
3030 return EIO;
3033 if (sys_errno == EINTR) {
3034 *retry = true;
3035 return sys_errno;
3038 if (sys_errno == EINPROGRESS) {
3039 *retry = true;
3040 return sys_errno;
3043 if (sys_errno == EAGAIN) {
3044 *retry = true;
3045 return sys_errno;
3048 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3049 if (sys_errno == ENOMEM) {
3050 *retry = true;
3051 return sys_errno;
3054 #ifdef EWOULDBLOCK
3055 #if EWOULDBLOCK != EAGAIN
3056 if (sys_errno == EWOULDBLOCK) {
3057 *retry = true;
3058 return sys_errno;
3060 #endif
3061 #endif
3063 return sys_errno;
3066 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3068 int ret;
3069 int err;
3070 bool retry;
3072 if (sconn->smb2.send_queue == NULL) {
3073 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3074 return NT_STATUS_OK;
3077 while (sconn->smb2.send_queue != NULL) {
3078 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3080 if (e->sendfile_header != NULL) {
3081 size_t size = 0;
3082 size_t i = 0;
3083 uint8_t *buf;
3085 for (i=0; i < e->count; i++) {
3086 size += e->vector[i].iov_len;
3089 if (size <= e->sendfile_header->length) {
3090 buf = e->sendfile_header->data;
3091 } else {
3092 buf = talloc_array(e->mem_ctx, uint8_t, size);
3093 if (buf == NULL) {
3094 return NT_STATUS_NO_MEMORY;
3098 size = 0;
3099 for (i=0; i < e->count; i++) {
3100 memcpy(buf+size,
3101 e->vector[i].iov_base,
3102 e->vector[i].iov_len);
3103 size += e->vector[i].iov_len;
3106 e->sendfile_header->data = buf;
3107 e->sendfile_header->length = size;
3108 e->count = 0;
3110 sconn->smb2.send_queue_len--;
3111 DLIST_REMOVE(sconn->smb2.send_queue, e);
3113 * This triggers the sendfile path via
3114 * the destructor.
3116 talloc_free(e->mem_ctx);
3117 continue;
3120 ret = writev(sconn->sock, e->vector, e->count);
3121 if (ret == 0) {
3122 /* propagate end of file */
3123 return NT_STATUS_INTERNAL_ERROR;
3125 err = socket_error_from_errno(ret, errno, &retry);
3126 if (retry) {
3127 /* retry later */
3128 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3129 return NT_STATUS_OK;
3131 if (err != 0) {
3132 return map_nt_error_from_unix_common(err);
3134 while (ret > 0) {
3135 if (ret < e->vector[0].iov_len) {
3136 uint8_t *base;
3137 base = (uint8_t *)e->vector[0].iov_base;
3138 base += ret;
3139 e->vector[0].iov_base = (void *)base;
3140 e->vector[0].iov_len -= ret;
3141 break;
3143 ret -= e->vector[0].iov_len;
3144 e->vector += 1;
3145 e->count -= 1;
3149 * there're maybe some empty vectors at the end
3150 * which we need to skip, otherwise we would get
3151 * ret == 0 from the readv() call and return EPIPE
3153 while (e->count > 0) {
3154 if (e->vector[0].iov_len > 0) {
3155 break;
3157 e->vector += 1;
3158 e->count -= 1;
3161 if (e->count > 0) {
3162 /* we have more to write */
3163 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3164 return NT_STATUS_OK;
3167 sconn->smb2.send_queue_len--;
3168 DLIST_REMOVE(sconn->smb2.send_queue, e);
3169 talloc_free(e->mem_ctx);
3172 return NT_STATUS_OK;
3175 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3176 uint16_t fde_flags)
3178 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3179 struct smbd_smb2_request *req = NULL;
3180 size_t min_recvfile_size = UINT32_MAX;
3181 int ret;
3182 int err;
3183 bool retry;
3184 NTSTATUS status;
3185 NTTIME now;
3187 if (!NT_STATUS_IS_OK(sconn->status)) {
3189 * we're not supposed to do any io
3191 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3192 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3193 return NT_STATUS_OK;
3196 if (fde_flags & TEVENT_FD_WRITE) {
3197 status = smbd_smb2_flush_send_queue(sconn);
3198 if (!NT_STATUS_IS_OK(status)) {
3199 return status;
3203 if (!(fde_flags & TEVENT_FD_READ)) {
3204 return NT_STATUS_OK;
3207 if (state->req == NULL) {
3208 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3209 return NT_STATUS_OK;
3212 again:
3213 if (!state->hdr.done) {
3214 state->hdr.done = true;
3216 state->vector.iov_base = (void *)state->hdr.nbt;
3217 state->vector.iov_len = NBT_HDR_SIZE;
3220 ret = readv(sconn->sock, &state->vector, 1);
3221 if (ret == 0) {
3222 /* propagate end of file */
3223 return NT_STATUS_END_OF_FILE;
3225 err = socket_error_from_errno(ret, errno, &retry);
3226 if (retry) {
3227 /* retry later */
3228 TEVENT_FD_READABLE(sconn->smb2.fde);
3229 return NT_STATUS_OK;
3231 if (err != 0) {
3232 return map_nt_error_from_unix_common(err);
3235 if (ret < state->vector.iov_len) {
3236 uint8_t *base;
3237 base = (uint8_t *)state->vector.iov_base;
3238 base += ret;
3239 state->vector.iov_base = (void *)base;
3240 state->vector.iov_len -= ret;
3241 /* we have more to read */
3242 TEVENT_FD_READABLE(sconn->smb2.fde);
3243 return NT_STATUS_OK;
3246 if (state->pktlen > 0) {
3247 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3249 * Not a possible receivefile write.
3250 * Read the rest of the data.
3252 state->doing_receivefile = false;
3254 state->pktbuf = talloc_realloc(state->req,
3255 state->pktbuf,
3256 uint8_t,
3257 state->pktfull);
3258 if (state->pktbuf == NULL) {
3259 return NT_STATUS_NO_MEMORY;
3262 state->vector.iov_base = (void *)(state->pktbuf +
3263 state->pktlen);
3264 state->vector.iov_len = (state->pktfull -
3265 state->pktlen);
3267 state->pktlen = state->pktfull;
3268 goto again;
3272 * Either this is a receivefile write so we've
3273 * done a short read, or if not we have all the data.
3275 goto got_full;
3279 * Now we analyze the NBT header
3281 if (state->hdr.nbt[0] != 0x00) {
3282 state->min_recv_size = 0;
3284 state->pktfull = smb2_len(state->hdr.nbt);
3285 if (state->pktfull == 0) {
3286 goto got_full;
3289 if (state->min_recv_size != 0) {
3290 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3291 min_recvfile_size += state->min_recv_size;
3294 if (state->pktfull > min_recvfile_size) {
3296 * Might be a receivefile write. Read the SMB2 HEADER +
3297 * SMB2_WRITE header first. Set 'doing_receivefile'
3298 * as we're *attempting* receivefile write. If this
3299 * turns out not to be a SMB2_WRITE request or otherwise
3300 * not suitable then we'll just read the rest of the data
3301 * the next time this function is called.
3303 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3304 state->doing_receivefile = true;
3305 } else {
3306 state->pktlen = state->pktfull;
3309 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3310 if (state->pktbuf == NULL) {
3311 return NT_STATUS_NO_MEMORY;
3314 state->vector.iov_base = (void *)state->pktbuf;
3315 state->vector.iov_len = state->pktlen;
3317 goto again;
3319 got_full:
3321 if (state->hdr.nbt[0] != 0x00) {
3322 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3323 state->hdr.nbt[0]));
3325 req = state->req;
3326 ZERO_STRUCTP(state);
3327 state->req = req;
3328 state->min_recv_size = lp_min_receive_file_size();
3329 req = NULL;
3330 goto again;
3333 req = state->req;
3334 state->req = NULL;
3336 req->request_time = timeval_current();
3337 now = timeval_to_nttime(&req->request_time);
3339 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3340 now,
3341 state->pktbuf,
3342 state->pktlen,
3343 req,
3344 &req->in.vector,
3345 &req->in.vector_count);
3346 if (!NT_STATUS_IS_OK(status)) {
3347 return status;
3350 if (state->doing_receivefile) {
3351 req->smb1req = talloc_zero(req, struct smb_request);
3352 if (req->smb1req == NULL) {
3353 return NT_STATUS_NO_MEMORY;
3355 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3358 ZERO_STRUCTP(state);
3360 req->current_idx = 1;
3362 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3363 req->current_idx, req->in.vector_count));
3365 status = smbd_smb2_request_validate(req);
3366 if (!NT_STATUS_IS_OK(status)) {
3367 return status;
3370 status = smbd_smb2_request_setup_out(req);
3371 if (!NT_STATUS_IS_OK(status)) {
3372 return status;
3375 status = smbd_smb2_request_dispatch(req);
3376 if (!NT_STATUS_IS_OK(status)) {
3377 return status;
3380 sconn->num_requests++;
3382 /* The timeout_processing function isn't run nearly
3383 often enough to implement 'max log size' without
3384 overrunning the size of the file by many megabytes.
3385 This is especially true if we are running at debug
3386 level 10. Checking every 50 SMB2s is a nice
3387 tradeoff of performance vs log file size overrun. */
3389 if ((sconn->num_requests % 50) == 0 &&
3390 need_to_check_log_size()) {
3391 change_to_root_user();
3392 check_log_size();
3395 status = smbd_smb2_request_next_incoming(sconn);
3396 if (!NT_STATUS_IS_OK(status)) {
3397 return status;
3400 return NT_STATUS_OK;
3403 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3404 struct tevent_fd *fde,
3405 uint16_t flags,
3406 void *private_data)
3408 struct smbd_server_connection *sconn =
3409 talloc_get_type_abort(private_data,
3410 struct smbd_server_connection);
3411 NTSTATUS status;
3413 status = smbd_smb2_io_handler(sconn, flags);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 smbd_server_connection_terminate(sconn, nt_errstr(status));
3416 return;