dsdb: use AS_SYSTEM | SHOW_RECYCLED for access check searches
[Samba/gebeck_regimport.git] / source3 / smbd / smb2_server.c
blobb031c6d153f42a5d3569af10c06455f58eab3ef7
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 #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9)
35 static const struct smbd_smb2_dispatch_table {
36 uint16_t opcode;
37 const char *name;
38 bool need_session;
39 bool need_tcon;
40 bool as_root;
41 uint16_t fileid_ofs;
42 bool allow_invalid_fileid;
43 } smbd_smb2_table[] = {
44 #define _OP(o) .opcode = o, .name = #o
46 _OP(SMB2_OP_NEGPROT),
47 .as_root = true,
48 },{
49 _OP(SMB2_OP_SESSSETUP),
50 .as_root = true,
51 },{
52 _OP(SMB2_OP_LOGOFF),
53 .need_session = true,
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_TCON),
57 .need_session = true,
59 * This call needs to be run as root.
61 * smbd_smb2_request_process_tcon()
62 * calls make_connection_snum(), which will call
63 * change_to_user(), when needed.
65 .as_root = true,
66 },{
67 _OP(SMB2_OP_TDIS),
68 .need_session = true,
69 .need_tcon = true,
70 .as_root = true,
71 },{
72 _OP(SMB2_OP_CREATE),
73 .need_session = true,
74 .need_tcon = true,
75 },{
76 _OP(SMB2_OP_CLOSE),
77 .need_session = true,
78 .need_tcon = true,
79 .fileid_ofs = 0x08,
80 },{
81 _OP(SMB2_OP_FLUSH),
82 .need_session = true,
83 .need_tcon = true,
84 .fileid_ofs = 0x08,
85 },{
86 _OP(SMB2_OP_READ),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x10,
90 },{
91 _OP(SMB2_OP_WRITE),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x10,
95 },{
96 _OP(SMB2_OP_LOCK),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x08,
101 _OP(SMB2_OP_IOCTL),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x08,
105 .allow_invalid_fileid = true,
107 _OP(SMB2_OP_CANCEL),
108 .as_root = true,
110 _OP(SMB2_OP_KEEPALIVE),
111 .as_root = true,
113 _OP(SMB2_OP_FIND),
114 .need_session = true,
115 .need_tcon = true,
116 .fileid_ofs = 0x08,
118 _OP(SMB2_OP_NOTIFY),
119 .need_session = true,
120 .need_tcon = true,
121 .fileid_ofs = 0x08,
123 _OP(SMB2_OP_GETINFO),
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x18,
128 _OP(SMB2_OP_SETINFO),
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x10,
133 _OP(SMB2_OP_BREAK),
134 .need_session = true,
135 .need_tcon = true,
137 * we do not set
138 * .fileid_ofs here
139 * as LEASE breaks does not
140 * have a file id
145 const char *smb2_opcode_name(uint16_t opcode)
147 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
148 return "Bad SMB2 opcode";
150 return smbd_smb2_table[opcode].name;
153 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
155 const struct smbd_smb2_dispatch_table *ret = NULL;
157 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
158 return NULL;
161 ret = &smbd_smb2_table[opcode];
163 SMB_ASSERT(ret->opcode == opcode);
165 return ret;
168 static void print_req_vectors(const struct smbd_smb2_request *req)
170 int i;
172 for (i = 0; i < req->in.vector_count; i++) {
173 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
174 (unsigned int)i,
175 (unsigned int)req->in.vector[i].iov_len);
177 for (i = 0; i < req->out.vector_count; i++) {
178 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
179 (unsigned int)i,
180 (unsigned int)req->out.vector[i].iov_len);
184 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
186 if (size < (4 + SMB2_HDR_BODY)) {
187 return false;
190 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
191 return false;
194 return true;
197 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
199 NTSTATUS status;
200 int ret;
202 TALLOC_FREE(sconn->smb1.fde);
204 sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
205 if (sconn->smb2.recv_queue == NULL) {
206 return NT_STATUS_NO_MEMORY;
209 sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
210 if (sconn->smb2.send_queue == NULL) {
211 return NT_STATUS_NO_MEMORY;
214 sconn->smb2.seqnum_low = 0;
215 sconn->smb2.seqnum_range = 1;
216 sconn->smb2.credits_granted = 1;
217 sconn->smb2.max_credits = lp_smb2_max_credits();
218 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
219 sconn->smb2.max_credits);
220 if (sconn->smb2.credits_bitmap == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 ret = tstream_bsd_existing_socket(sconn, sconn->sock,
225 &sconn->smb2.stream);
226 if (ret == -1) {
227 status = map_nt_error_from_unix(errno);
228 return status;
231 /* Ensure child is set to non-blocking mode */
232 set_blocking(sconn->sock, false);
233 return NT_STATUS_OK;
236 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
237 #define _smb2_setlen(_buf,len) do { \
238 uint8_t *buf = (uint8_t *)_buf; \
239 buf[0] = 0; \
240 buf[1] = ((len)&0xFF0000)>>16; \
241 buf[2] = ((len)&0xFF00)>>8; \
242 buf[3] = (len)&0xFF; \
243 } while (0)
245 static void smb2_setup_nbt_length(struct iovec *vector, int count)
247 size_t len = 0;
248 int i;
250 for (i=1; i < count; i++) {
251 len += vector[i].iov_len;
254 _smb2_setlen(vector[0].iov_base, len);
257 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
259 data_blob_clear_free(&req->first_key);
260 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_pool(mem_ctx, 8192);
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 TALLOC_FREE(mem_pool);
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 *conn,
296 NTTIME now,
297 uint8_t *buf,
298 size_t buflen,
299 TALLOC_CTX *mem_ctx,
300 struct iovec **piov,
301 int *pnum_iov)
303 struct iovec *iov;
304 int num_iov = 1;
305 size_t taken = 0;
306 uint8_t *first_hdr = buf;
307 size_t verified_buflen = 0;
308 uint8_t *tf = NULL;
309 size_t tf_len = 0;
312 * Note: index '0' is reserved for the transport protocol
314 iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
315 if (iov == NULL) {
316 return NT_STATUS_NO_MEMORY;
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_tmp;
331 if (verified_buflen > taken) {
332 len = verified_buflen - taken;
333 } else {
334 tf = NULL;
335 tf_len = 0;
338 if (len < 4) {
339 DEBUG(10, ("%d bytes left, expected at least %d\n",
340 (int)len, 4));
341 goto inval;
343 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
344 struct smbXsrv_session *s = NULL;
345 uint64_t uid;
346 struct iovec tf_iov[2];
347 NTSTATUS status;
348 size_t enc_len;
350 if (conn->protocol < PROTOCOL_SMB2_24) {
351 DEBUG(10, ("Got SMB2_TRANSFORM header, "
352 "but dialect[0x%04X] is used\n",
353 conn->smb2.server.dialect));
354 goto inval;
357 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
358 DEBUG(10, ("Got SMB2_TRANSFORM header, "
359 "but not negotiated "
360 "client[0x%08X] server[0x%08X]\n",
361 conn->smb2.client.capabilities,
362 conn->smb2.server.capabilities));
363 goto inval;
366 if (len < SMB2_TF_HDR_SIZE) {
367 DEBUG(1, ("%d bytes left, expected at least %d\n",
368 (int)len, SMB2_TF_HDR_SIZE));
369 goto inval;
371 tf = hdr;
372 tf_len = SMB2_TF_HDR_SIZE;
373 taken += tf_len;
375 hdr = first_hdr + taken;
376 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
377 uid = BVAL(tf, SMB2_TF_SESSION_ID);
379 if (len < SMB2_TF_HDR_SIZE + enc_len) {
380 DEBUG(1, ("%d bytes left, expected at least %d\n",
381 (int)len,
382 (int)(SMB2_TF_HDR_SIZE + enc_len)));
383 goto inval;
386 status = smb2srv_session_lookup(conn, uid, now, &s);
387 if (s == NULL) {
388 DEBUG(1, ("invalid session[%llu] in "
389 "SMB2_TRANSFORM header\n",
390 (unsigned long long)uid));
391 TALLOC_FREE(iov);
392 return NT_STATUS_USER_SESSION_DELETED;
395 tf_iov[0].iov_base = (void *)tf;
396 tf_iov[0].iov_len = tf_len;
397 tf_iov[1].iov_base = (void *)hdr;
398 tf_iov[1].iov_len = enc_len;
400 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
401 conn->protocol,
402 tf_iov, 2);
403 if (!NT_STATUS_IS_OK(status)) {
404 TALLOC_FREE(iov);
405 return status;
408 verified_buflen = taken + enc_len;
409 len = enc_len;
413 * We need the header plus the body length field
416 if (len < SMB2_HDR_BODY + 2) {
417 DEBUG(10, ("%d bytes left, expected at least %d\n",
418 (int)len, SMB2_HDR_BODY));
419 goto inval;
421 if (IVAL(hdr, 0) != SMB2_MAGIC) {
422 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
423 IVAL(hdr, 0)));
424 goto inval;
426 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
427 DEBUG(10, ("Got HDR len %d, expected %d\n",
428 SVAL(hdr, 4), SMB2_HDR_BODY));
429 goto inval;
432 full_size = len;
433 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
434 body_size = SVAL(hdr, SMB2_HDR_BODY);
436 if (next_command_ofs != 0) {
437 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
438 goto inval;
440 if (next_command_ofs > full_size) {
441 goto inval;
443 full_size = next_command_ofs;
445 if (body_size < 2) {
446 goto inval;
448 body_size &= 0xfffe;
450 if (body_size > (full_size - SMB2_HDR_BODY)) {
452 * let the caller handle the error
454 body_size = full_size - SMB2_HDR_BODY;
456 body = hdr + SMB2_HDR_BODY;
457 dyn = body + body_size;
458 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
460 iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
461 num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
462 if (iov_tmp == NULL) {
463 TALLOC_FREE(iov);
464 return NT_STATUS_NO_MEMORY;
466 iov = iov_tmp;
467 cur = &iov[num_iov];
468 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
470 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
471 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
472 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
473 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
474 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
475 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
476 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
477 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
479 taken += full_size;
482 *piov = iov;
483 *pnum_iov = num_iov;
484 return NT_STATUS_OK;
486 inval:
487 TALLOC_FREE(iov);
488 return NT_STATUS_INVALID_PARAMETER;
491 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
492 uint8_t *inbuf, size_t size,
493 struct smbd_smb2_request **_req)
495 struct smbd_smb2_request *req;
496 uint32_t protocol_version;
497 const uint8_t *inhdr = NULL;
498 uint16_t cmd;
499 uint32_t next_command_ofs;
500 NTSTATUS status;
501 NTTIME now;
503 if (size < (4 + SMB2_HDR_BODY + 2)) {
504 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
505 return NT_STATUS_INVALID_PARAMETER;
508 inhdr = inbuf + 4;
510 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
511 if (protocol_version != SMB2_MAGIC) {
512 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
513 protocol_version));
514 return NT_STATUS_INVALID_PARAMETER;
517 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
518 if (cmd != SMB2_OP_NEGPROT) {
519 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
520 cmd));
521 return NT_STATUS_INVALID_PARAMETER;
524 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
525 if (next_command_ofs != 0) {
526 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
527 next_command_ofs));
528 return NT_STATUS_INVALID_PARAMETER;
531 req = smbd_smb2_request_allocate(sconn);
532 if (req == NULL) {
533 return NT_STATUS_NO_MEMORY;
535 req->sconn = sconn;
537 talloc_steal(req, inbuf);
539 req->request_time = timeval_current();
540 now = timeval_to_nttime(&req->request_time);
542 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
543 now,
544 inbuf + NBT_HDR_SIZE,
545 size - NBT_HDR_SIZE,
546 req, &req->in.vector,
547 &req->in.vector_count);
548 if (!NT_STATUS_IS_OK(status)) {
549 TALLOC_FREE(req);
550 return status;
553 req->current_idx = 1;
555 *_req = req;
556 return NT_STATUS_OK;
559 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
560 uint64_t message_id, uint64_t seq_id)
562 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
563 unsigned int offset;
565 if (seq_id < sconn->smb2.seqnum_low) {
566 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
567 "%llu (sequence id %llu) "
568 "(granted = %u, low = %llu, range = %u)\n",
569 (unsigned long long)message_id,
570 (unsigned long long)seq_id,
571 (unsigned int)sconn->smb2.credits_granted,
572 (unsigned long long)sconn->smb2.seqnum_low,
573 (unsigned int)sconn->smb2.seqnum_range));
574 return false;
577 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
578 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
579 "%llu (sequence id %llu) "
580 "(granted = %u, low = %llu, range = %u)\n",
581 (unsigned long long)message_id,
582 (unsigned long long)seq_id,
583 (unsigned int)sconn->smb2.credits_granted,
584 (unsigned long long)sconn->smb2.seqnum_low,
585 (unsigned int)sconn->smb2.seqnum_range));
586 return false;
589 offset = seq_id % sconn->smb2.max_credits;
591 if (bitmap_query(credits_bm, offset)) {
592 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
593 "%llu (sequence id %llu) "
594 "(granted = %u, low = %llu, range = %u) "
595 "(bm offset %u)\n",
596 (unsigned long long)message_id,
597 (unsigned long long)seq_id,
598 (unsigned int)sconn->smb2.credits_granted,
599 (unsigned long long)sconn->smb2.seqnum_low,
600 (unsigned int)sconn->smb2.seqnum_range,
601 offset));
602 return false;
605 /* Mark the message_ids as seen in the bitmap. */
606 bitmap_set(credits_bm, offset);
608 if (seq_id != sconn->smb2.seqnum_low) {
609 return true;
613 * Move the window forward by all the message_id's
614 * already seen.
616 while (bitmap_query(credits_bm, offset)) {
617 DEBUG(10,("smb2_validate_sequence_number: clearing "
618 "id %llu (position %u) from bitmap\n",
619 (unsigned long long)(sconn->smb2.seqnum_low),
620 offset));
621 bitmap_clear(credits_bm, offset);
623 sconn->smb2.seqnum_low += 1;
624 sconn->smb2.seqnum_range -= 1;
625 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
628 return true;
631 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
632 const uint8_t *inhdr)
634 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
635 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
636 uint16_t credit_charge = 1;
637 uint64_t i;
639 if (opcode == SMB2_OP_CANCEL) {
640 /* SMB2_CANCEL requests by definition resend messageids. */
641 return true;
644 if (sconn->smb2.supports_multicredit) {
645 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
646 credit_charge = MAX(credit_charge, 1);
649 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
650 "credits_granted %llu, "
651 "seqnum low/range: %llu/%llu\n",
652 (unsigned long long) message_id,
653 (unsigned long long) credit_charge,
654 (unsigned long long) sconn->smb2.credits_granted,
655 (unsigned long long) sconn->smb2.seqnum_low,
656 (unsigned long long) sconn->smb2.seqnum_range));
658 if (sconn->smb2.credits_granted < credit_charge) {
659 DEBUG(0, ("smb2_validate_message_id: client used more "
660 "credits than granted, mid %llu, charge %llu, "
661 "credits_granted %llu, "
662 "seqnum low/range: %llu/%llu\n",
663 (unsigned long long) message_id,
664 (unsigned long long) credit_charge,
665 (unsigned long long) sconn->smb2.credits_granted,
666 (unsigned long long) sconn->smb2.seqnum_low,
667 (unsigned long long) sconn->smb2.seqnum_range));
668 return false;
672 * now check the message ids
674 * for multi-credit requests we need to check all current mid plus
675 * the implicit mids caused by the credit charge
676 * e.g. current mid = 15, charge 5 => mark 15-19 as used
679 for (i = 0; i <= (credit_charge-1); i++) {
680 uint64_t id = message_id + i;
681 bool ok;
683 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
684 (unsigned long long)message_id,
685 credit_charge,
686 (unsigned long long)id));
688 ok = smb2_validate_sequence_number(sconn, message_id, id);
689 if (!ok) {
690 return false;
694 /* substract used credits */
695 sconn->smb2.credits_granted -= credit_charge;
697 return true;
700 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
702 int count;
703 int idx;
705 count = req->in.vector_count;
707 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
708 /* It's not a SMB2 request */
709 return NT_STATUS_INVALID_PARAMETER;
712 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
713 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
714 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
715 const uint8_t *inhdr = NULL;
717 if (hdr->iov_len != SMB2_HDR_BODY) {
718 return NT_STATUS_INVALID_PARAMETER;
721 if (body->iov_len < 2) {
722 return NT_STATUS_INVALID_PARAMETER;
725 inhdr = (const uint8_t *)hdr->iov_base;
727 /* Check the SMB2 header */
728 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
729 return NT_STATUS_INVALID_PARAMETER;
732 if (!smb2_validate_message_id(req->sconn, inhdr)) {
733 return NT_STATUS_INVALID_PARAMETER;
737 return NT_STATUS_OK;
740 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
741 const struct iovec *in_vector,
742 struct iovec *out_vector)
744 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
745 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
746 uint16_t credit_charge = 1;
747 uint16_t credits_requested;
748 uint32_t out_flags;
749 uint16_t cmd;
750 NTSTATUS out_status;
751 uint16_t credits_granted = 0;
752 uint64_t credits_possible;
753 uint16_t current_max_credits;
756 * first we grant only 1/16th of the max range.
758 * Windows also starts with the 1/16th and then grants
759 * more later. I was only able to trigger higher
760 * values, when using a very high credit charge.
762 * TODO: scale up depending on load, free memory
763 * or other stuff.
764 * Maybe also on the relationship between number
765 * of requests and the used sequence number.
766 * Which means we would grant more credits
767 * for client which use multi credit requests.
769 current_max_credits = sconn->smb2.max_credits / 16;
770 current_max_credits = MAX(current_max_credits, 1);
772 if (sconn->smb2.supports_multicredit) {
773 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
774 credit_charge = MAX(credit_charge, 1);
777 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
778 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
779 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
780 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
782 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
784 if (sconn->smb2.max_credits < credit_charge) {
785 smbd_server_connection_terminate(sconn,
786 "client error: credit charge > max credits\n");
787 return;
790 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
792 * In case we already send an async interim
793 * response, we should not grant
794 * credits on the final response.
796 credits_granted = 0;
797 } else if (credits_requested > 0) {
798 uint16_t additional_max = 0;
799 uint16_t additional_credits = credits_requested - 1;
801 switch (cmd) {
802 case SMB2_OP_NEGPROT:
803 break;
804 case SMB2_OP_SESSSETUP:
806 * Windows 2012 RC1 starts to grant
807 * additional credits
808 * with a successful session setup
810 if (NT_STATUS_IS_OK(out_status)) {
811 additional_max = 32;
813 break;
814 default:
816 * We match windows and only grant additional credits
817 * in chunks of 32.
819 additional_max = 32;
820 break;
823 additional_credits = MIN(additional_credits, additional_max);
825 credits_granted = credit_charge + additional_credits;
826 } else if (sconn->smb2.credits_granted == 0) {
828 * Make sure the client has always at least one credit
830 credits_granted = 1;
834 * sequence numbers should not wrap
836 * 1. calculate the possible credits until
837 * the sequence numbers start to wrap on 64-bit.
839 * 2. UINT64_MAX is used for Break Notifications.
841 * 2. truncate the possible credits to the maximum
842 * credits we want to grant to the client in total.
844 * 3. remove the range we'll already granted to the client
845 * this makes sure the client consumes the lowest sequence
846 * number, before we can grant additional credits.
848 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
849 if (credits_possible > 0) {
850 /* remove UINT64_MAX */
851 credits_possible -= 1;
853 credits_possible = MIN(credits_possible, current_max_credits);
854 credits_possible -= sconn->smb2.seqnum_range;
856 credits_granted = MIN(credits_granted, credits_possible);
858 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
859 sconn->smb2.credits_granted += credits_granted;
860 sconn->smb2.seqnum_range += credits_granted;
862 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
863 "granted %u, current possible/max %u/%u, "
864 "total granted/max/low/range %u/%u/%llu/%u\n",
865 (unsigned int)credits_requested,
866 (unsigned int)credit_charge,
867 (unsigned int)credits_granted,
868 (unsigned int)credits_possible,
869 (unsigned int)current_max_credits,
870 (unsigned int)sconn->smb2.credits_granted,
871 (unsigned int)sconn->smb2.max_credits,
872 (unsigned long long)sconn->smb2.seqnum_low,
873 (unsigned int)sconn->smb2.seqnum_range));
876 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
877 struct smbd_smb2_request *outreq)
879 int count, idx;
880 uint16_t total_credits = 0;
882 count = outreq->out.vector_count;
884 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
885 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
886 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
887 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
889 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
891 /* To match Windows, count up what we
892 just granted. */
893 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
894 /* Set to zero in all but the last reply. */
895 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
896 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
897 } else {
898 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
903 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
905 struct iovec *vector;
906 int count;
907 int idx;
909 count = req->in.vector_count;
910 vector = talloc_zero_array(req, struct iovec, count);
911 if (vector == NULL) {
912 return NT_STATUS_NO_MEMORY;
915 vector[0].iov_base = req->out.nbt_hdr;
916 vector[0].iov_len = 4;
917 SIVAL(req->out.nbt_hdr, 0, 0);
919 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
920 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
921 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
922 uint8_t *outhdr = NULL;
923 uint8_t *outbody = NULL;
924 uint32_t next_command_ofs = 0;
925 struct iovec *current = &vector[idx];
927 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
928 /* we have a next command -
929 * setup for the error case. */
930 next_command_ofs = SMB2_HDR_BODY + 9;
933 outhdr = talloc_zero_array(vector, uint8_t,
934 OUTVEC_ALLOC_SIZE);
935 if (outhdr == NULL) {
936 return NT_STATUS_NO_MEMORY;
939 outbody = outhdr + SMB2_HDR_BODY;
942 * SMBD_SMB2_TF_IOV_OFS might be used later
944 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
945 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
947 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
948 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
950 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
951 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
953 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
954 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
956 /* setup the SMB2 header */
957 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
958 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
959 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
960 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
961 SIVAL(outhdr, SMB2_HDR_STATUS,
962 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
963 SSVAL(outhdr, SMB2_HDR_OPCODE,
964 SVAL(inhdr, SMB2_HDR_OPCODE));
965 SIVAL(outhdr, SMB2_HDR_FLAGS,
966 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
967 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
968 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
969 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
970 SIVAL(outhdr, SMB2_HDR_PID,
971 IVAL(inhdr, SMB2_HDR_PID));
972 SIVAL(outhdr, SMB2_HDR_TID,
973 IVAL(inhdr, SMB2_HDR_TID));
974 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
975 BVAL(inhdr, SMB2_HDR_SESSION_ID));
976 memcpy(outhdr + SMB2_HDR_SIGNATURE,
977 inhdr + SMB2_HDR_SIGNATURE, 16);
979 /* setup error body header */
980 SSVAL(outbody, 0x00, 0x08 + 1);
981 SSVAL(outbody, 0x02, 0);
982 SIVAL(outbody, 0x04, 0);
985 req->out.vector = vector;
986 req->out.vector_count = count;
988 /* setup the length of the NBT packet */
989 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
991 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
993 return NT_STATUS_OK;
996 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
997 const char *reason,
998 const char *location)
1000 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1001 reason, location));
1002 exit_server_cleanly(reason);
1005 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1006 struct iovec *outvec,
1007 const struct iovec *srcvec)
1009 const uint8_t *srctf;
1010 size_t srctf_len;
1011 const uint8_t *srchdr;
1012 size_t srchdr_len;
1013 const uint8_t *srcbody;
1014 size_t srcbody_len;
1015 const uint8_t *expected_srcbody;
1016 const uint8_t *srcdyn;
1017 size_t srcdyn_len;
1018 const uint8_t *expected_srcdyn;
1019 uint8_t *dsttf;
1020 uint8_t *dsthdr;
1021 uint8_t *dstbody;
1022 uint8_t *dstdyn;
1024 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1025 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1026 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1027 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1028 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1029 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1030 expected_srcbody = srchdr + SMB2_HDR_BODY;
1031 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1032 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1033 expected_srcdyn = srcbody + 8;
1035 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1036 return false;
1039 if (srchdr_len != SMB2_HDR_BODY) {
1040 return false;
1043 if (srctf_len == SMB2_TF_HDR_SIZE) {
1044 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1045 if (dsttf == NULL) {
1046 return false;
1048 } else {
1049 dsttf = NULL;
1051 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1052 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1054 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1055 * be allocated with size OUTVEC_ALLOC_SIZE. */
1057 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1058 if (dsthdr == NULL) {
1059 return false;
1061 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1062 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1065 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1066 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1067 * then duplicate this. Else use talloc_memdup().
1070 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1071 dstbody = dsthdr + SMB2_HDR_BODY;
1072 } else {
1073 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1074 if (dstbody == NULL) {
1075 return false;
1078 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1079 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1082 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1083 * pointing to
1084 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1085 * then duplicate this. Else use talloc_memdup().
1088 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1089 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1090 } else if (srcdyn == NULL) {
1091 dstdyn = NULL;
1092 } else {
1093 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1094 if (dstdyn == NULL) {
1095 return false;
1098 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1099 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1101 return true;
1104 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1106 struct smbd_smb2_request *newreq = NULL;
1107 struct iovec *outvec = NULL;
1108 int count = req->out.vector_count;
1109 int i;
1111 newreq = smbd_smb2_request_allocate(req->sconn);
1112 if (!newreq) {
1113 return NULL;
1116 newreq->sconn = req->sconn;
1117 newreq->session = req->session;
1118 newreq->do_encryption = req->do_encryption;
1119 newreq->do_signing = req->do_signing;
1120 newreq->current_idx = req->current_idx;
1122 outvec = talloc_zero_array(newreq, struct iovec, count);
1123 if (!outvec) {
1124 TALLOC_FREE(newreq);
1125 return NULL;
1127 newreq->out.vector = outvec;
1128 newreq->out.vector_count = count;
1130 /* Setup the outvec's identically to req. */
1131 outvec[0].iov_base = newreq->out.nbt_hdr;
1132 outvec[0].iov_len = 4;
1133 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1135 /* Setup the vectors identically to the ones in req. */
1136 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1137 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1138 break;
1142 if (i < count) {
1143 /* Alloc failed. */
1144 TALLOC_FREE(newreq);
1145 return NULL;
1148 smb2_setup_nbt_length(newreq->out.vector,
1149 newreq->out.vector_count);
1151 return newreq;
1154 static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
1156 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1158 struct smbXsrv_connection *conn = req->sconn->conn;
1159 int first_idx = 1;
1160 struct iovec *firsttf = NULL;
1161 struct iovec *outhdr_v = NULL;
1162 uint8_t *outhdr = NULL;
1163 struct smbd_smb2_request *nreq = NULL;
1164 NTSTATUS status;
1166 /* Create a new smb2 request we'll use
1167 for the interim return. */
1168 nreq = dup_smb2_req(req);
1169 if (!nreq) {
1170 return NT_STATUS_NO_MEMORY;
1173 /* Lose the last X out vectors. They're the
1174 ones we'll be using for the async reply. */
1175 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1177 smb2_setup_nbt_length(nreq->out.vector,
1178 nreq->out.vector_count);
1180 /* Step back to the previous reply. */
1181 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1182 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1183 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1184 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1185 /* And end the chain. */
1186 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1188 /* Calculate outgoing credits */
1189 smb2_calculate_credits(req, nreq);
1191 if (DEBUGLEVEL >= 10) {
1192 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1193 (unsigned int)nreq->current_idx );
1194 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1195 (unsigned int)nreq->out.vector_count );
1196 print_req_vectors(nreq);
1200 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1201 * we need to sign/encrypt here with the last/first key we remembered
1203 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1204 status = smb2_signing_encrypt_pdu(req->first_key,
1205 conn->protocol,
1206 firsttf,
1207 nreq->out.vector_count - first_idx);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 return status;
1211 } else if (req->last_key.length > 0) {
1212 status = smb2_signing_sign_pdu(req->last_key,
1213 conn->protocol,
1214 outhdr_v,
1215 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 return status;
1221 nreq->subreq = tstream_writev_queue_send(nreq,
1222 nreq->sconn->ev_ctx,
1223 nreq->sconn->smb2.stream,
1224 nreq->sconn->smb2.send_queue,
1225 nreq->out.vector,
1226 nreq->out.vector_count);
1228 if (nreq->subreq == NULL) {
1229 return NT_STATUS_NO_MEMORY;
1232 tevent_req_set_callback(nreq->subreq,
1233 smbd_smb2_request_writev_done,
1234 nreq);
1236 return NT_STATUS_OK;
1239 struct smbd_smb2_request_pending_state {
1240 struct smbd_server_connection *sconn;
1241 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1242 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1245 static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
1247 struct smbd_smb2_request_pending_state *state =
1248 tevent_req_callback_data(subreq,
1249 struct smbd_smb2_request_pending_state);
1250 struct smbd_server_connection *sconn = state->sconn;
1251 int ret;
1252 int sys_errno;
1254 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1255 TALLOC_FREE(subreq);
1256 if (ret == -1) {
1257 NTSTATUS status = map_nt_error_from_unix(sys_errno);
1258 smbd_server_connection_terminate(sconn, nt_errstr(status));
1259 return;
1262 TALLOC_FREE(state);
1265 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1266 struct tevent_timer *te,
1267 struct timeval current_time,
1268 void *private_data);
1270 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1271 struct tevent_req *subreq,
1272 uint32_t defer_time)
1274 NTSTATUS status;
1275 struct timeval defer_endtime;
1276 uint8_t *outhdr = NULL;
1277 uint32_t flags;
1279 if (!tevent_req_is_in_progress(subreq)) {
1280 return NT_STATUS_OK;
1283 req->subreq = subreq;
1284 subreq = NULL;
1286 if (req->async_te) {
1287 /* We're already async. */
1288 return NT_STATUS_OK;
1291 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1292 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1293 if (flags & SMB2_HDR_FLAG_ASYNC) {
1294 /* We're already async. */
1295 return NT_STATUS_OK;
1298 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1300 * We're trying to go async in a compound
1301 * request chain.
1302 * This is only allowed for opens that
1303 * cause an oplock break, otherwise it
1304 * is not allowed. See [MS-SMB2].pdf
1305 * note <194> on Section 3.3.5.2.7.
1307 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1309 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1311 * Cancel the outstanding request.
1313 bool ok = tevent_req_cancel(req->subreq);
1314 if (ok) {
1315 return NT_STATUS_OK;
1317 TALLOC_FREE(req->subreq);
1318 return smbd_smb2_request_error(req,
1319 NT_STATUS_INTERNAL_ERROR);
1323 if (DEBUGLEVEL >= 10) {
1324 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1325 (unsigned int)req->current_idx );
1326 print_req_vectors(req);
1329 if (req->current_idx > 1) {
1331 * We're going async in a compound
1332 * chain after the first request has
1333 * already been processed. Send an
1334 * interim response containing the
1335 * set of replies already generated.
1337 int idx = req->current_idx;
1339 status = smb2_send_async_interim_response(req);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 return status;
1343 data_blob_clear_free(&req->first_key);
1345 req->current_idx = 1;
1348 * Re-arrange the in.vectors to remove what
1349 * we just sent.
1351 memmove(&req->in.vector[1],
1352 &req->in.vector[idx],
1353 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1354 req->in.vector_count = 1 + (req->in.vector_count - idx);
1356 /* Re-arrange the out.vectors to match. */
1357 memmove(&req->out.vector[1],
1358 &req->out.vector[idx],
1359 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1360 req->out.vector_count = 1 + (req->out.vector_count - idx);
1362 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1364 * We only have one remaining request as
1365 * we've processed everything else.
1366 * This is no longer a compound request.
1368 req->compound_related = false;
1369 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1370 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1371 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1374 data_blob_clear_free(&req->last_key);
1376 defer_endtime = timeval_current_ofs_usec(defer_time);
1377 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1378 req, defer_endtime,
1379 smbd_smb2_request_pending_timer,
1380 req);
1381 if (req->async_te == NULL) {
1382 return NT_STATUS_NO_MEMORY;
1385 return NT_STATUS_OK;
1388 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1389 struct tevent_timer *te,
1390 struct timeval current_time,
1391 void *private_data)
1393 struct smbd_smb2_request *req =
1394 talloc_get_type_abort(private_data,
1395 struct smbd_smb2_request);
1396 struct smbd_smb2_request_pending_state *state = NULL;
1397 uint8_t *outhdr = NULL;
1398 const uint8_t *inhdr = NULL;
1399 uint8_t *tf = NULL;
1400 size_t tf_len = 0;
1401 uint8_t *hdr = NULL;
1402 uint8_t *body = NULL;
1403 uint8_t *dyn = NULL;
1404 uint32_t flags = 0;
1405 uint64_t session_id = 0;
1406 uint64_t message_id = 0;
1407 uint64_t nonce_high = 0;
1408 uint64_t nonce_low = 0;
1409 uint64_t async_id = 0;
1410 struct tevent_req *subreq = NULL;
1412 TALLOC_FREE(req->async_te);
1414 /* Ensure our final reply matches the interim one. */
1415 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1416 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1417 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1418 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1419 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1421 async_id = message_id; /* keep it simple for now... */
1423 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1424 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1426 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1427 "going async\n",
1428 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1429 (unsigned long long)async_id ));
1432 * What we send is identical to a smbd_smb2_request_error
1433 * packet with an error status of STATUS_PENDING. Make use
1434 * of this fact sometime when refactoring. JRA.
1437 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1438 if (state == NULL) {
1439 smbd_server_connection_terminate(req->sconn,
1440 nt_errstr(NT_STATUS_NO_MEMORY));
1441 return;
1443 state->sconn = req->sconn;
1445 tf = state->buf + NBT_HDR_SIZE;
1446 tf_len = SMB2_TF_HDR_SIZE;
1448 hdr = tf + SMB2_TF_HDR_SIZE;
1449 body = hdr + SMB2_HDR_BODY;
1450 dyn = body + 8;
1452 if (req->do_encryption) {
1453 struct smbXsrv_session *x = req->session;
1455 nonce_high = x->nonce_high;
1456 nonce_low = x->nonce_low;
1458 x->nonce_low += 1;
1459 if (x->nonce_low == 0) {
1460 x->nonce_low += 1;
1461 x->nonce_high += 1;
1465 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1466 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1467 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1468 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1470 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1471 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1472 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1473 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1474 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1476 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1477 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1478 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1479 SBVAL(hdr, SMB2_HDR_PID, async_id);
1480 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1481 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1482 memcpy(hdr+SMB2_HDR_SIGNATURE,
1483 outhdr+SMB2_HDR_SIGNATURE, 16);
1485 SSVAL(body, 0x00, 0x08 + 1);
1487 SCVAL(body, 0x02, 0);
1488 SCVAL(body, 0x03, 0);
1489 SIVAL(body, 0x04, 0);
1490 /* Match W2K8R2... */
1491 SCVAL(dyn, 0x00, 0x21);
1493 state->vector[0].iov_base = (void *)state->buf;
1494 state->vector[0].iov_len = NBT_HDR_SIZE;
1496 if (req->do_encryption) {
1497 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1498 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1499 } else {
1500 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1501 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1504 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1505 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1507 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1508 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1510 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1511 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1513 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1515 /* Ensure we correctly go through crediting. Grant
1516 the credits now, and zero credits on the final
1517 response. */
1518 smb2_set_operation_credit(req->sconn,
1519 SMBD_SMB2_IN_HDR_IOV(req),
1520 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1522 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1524 if (DEBUGLVL(10)) {
1525 int i;
1527 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1528 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1529 (unsigned int)i,
1530 (unsigned int)ARRAY_SIZE(state->vector),
1531 (unsigned int)state->vector[i].iov_len);
1535 if (req->do_encryption) {
1536 NTSTATUS status;
1537 struct smbXsrv_session *x = req->session;
1538 struct smbXsrv_connection *conn = x->connection;
1539 DATA_BLOB encryption_key = x->global->encryption_key;
1541 status = smb2_signing_encrypt_pdu(encryption_key,
1542 conn->protocol,
1543 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1544 SMBD_SMB2_NUM_IOV_PER_REQ);
1545 if (!NT_STATUS_IS_OK(status)) {
1546 smbd_server_connection_terminate(req->sconn,
1547 nt_errstr(status));
1548 return;
1550 } else if (req->do_signing) {
1551 NTSTATUS status;
1552 struct smbXsrv_session *x = req->session;
1553 struct smbXsrv_connection *conn = x->connection;
1554 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1556 status = smb2_signing_sign_pdu(signing_key,
1557 conn->protocol,
1558 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1559 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 smbd_server_connection_terminate(req->sconn,
1562 nt_errstr(status));
1563 return;
1567 subreq = tstream_writev_queue_send(state,
1568 state->sconn->ev_ctx,
1569 state->sconn->smb2.stream,
1570 state->sconn->smb2.send_queue,
1571 state->vector,
1572 ARRAY_SIZE(state->vector));
1573 if (subreq == NULL) {
1574 smbd_server_connection_terminate(state->sconn,
1575 nt_errstr(NT_STATUS_NO_MEMORY));
1576 return;
1578 tevent_req_set_callback(subreq,
1579 smbd_smb2_request_pending_writev_done,
1580 state);
1583 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1585 struct smbd_server_connection *sconn = req->sconn;
1586 struct smbd_smb2_request *cur;
1587 const uint8_t *inhdr;
1588 uint32_t flags;
1589 uint64_t search_message_id;
1590 uint64_t search_async_id;
1591 uint64_t found_id;
1593 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1595 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1596 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1597 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1600 * we don't need the request anymore
1601 * cancel requests never have a response
1603 DLIST_REMOVE(req->sconn->smb2.requests, req);
1604 TALLOC_FREE(req);
1606 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1607 const uint8_t *outhdr;
1608 uint64_t message_id;
1609 uint64_t async_id;
1611 if (cur->compound_related) {
1613 * Never cancel anything in a compound request.
1614 * Way too hard to deal with the result.
1616 continue;
1619 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1621 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1622 async_id = BVAL(outhdr, SMB2_HDR_PID);
1624 if (flags & SMB2_HDR_FLAG_ASYNC) {
1625 if (search_async_id == async_id) {
1626 found_id = async_id;
1627 break;
1629 } else {
1630 if (search_message_id == message_id) {
1631 found_id = message_id;
1632 break;
1637 if (cur && cur->subreq) {
1638 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1639 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1640 "cancel opcode[%s] mid %llu\n",
1641 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1642 (unsigned long long)found_id ));
1643 tevent_req_cancel(cur->subreq);
1646 return NT_STATUS_OK;
1649 /*************************************************************
1650 Ensure an incoming tid is a valid one for us to access.
1651 Change to the associated uid credentials and chdir to the
1652 valid tid directory.
1653 *************************************************************/
1655 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1657 const uint8_t *inhdr;
1658 uint32_t in_flags;
1659 uint32_t in_tid;
1660 struct smbXsrv_tcon *tcon;
1661 NTSTATUS status;
1662 NTTIME now = timeval_to_nttime(&req->request_time);
1664 req->tcon = NULL;
1666 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1668 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1669 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1671 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1672 in_tid = req->last_tid;
1675 req->last_tid = 0;
1677 status = smb2srv_tcon_lookup(req->session,
1678 in_tid, now, &tcon);
1679 if (!NT_STATUS_IS_OK(status)) {
1680 return status;
1683 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1684 return NT_STATUS_ACCESS_DENIED;
1687 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1688 if (!set_current_service(tcon->compat, 0, true)) {
1689 return NT_STATUS_ACCESS_DENIED;
1692 req->tcon = tcon;
1693 req->last_tid = in_tid;
1695 return NT_STATUS_OK;
1698 /*************************************************************
1699 Ensure an incoming session_id is a valid one for us to access.
1700 *************************************************************/
1702 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1704 const uint8_t *inhdr;
1705 uint32_t in_flags;
1706 uint16_t in_opcode;
1707 uint64_t in_session_id;
1708 struct smbXsrv_session *session = NULL;
1709 struct auth_session_info *session_info;
1710 NTSTATUS status;
1711 NTTIME now = timeval_to_nttime(&req->request_time);
1713 req->session = NULL;
1714 req->tcon = NULL;
1716 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1718 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1719 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1720 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1722 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1723 in_session_id = req->last_session_id;
1726 req->last_session_id = 0;
1728 /* lookup an existing session */
1729 status = smb2srv_session_lookup(req->sconn->conn,
1730 in_session_id, now,
1731 &session);
1732 if (session) {
1733 req->session = session;
1734 req->last_session_id = in_session_id;
1736 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1737 switch (in_opcode) {
1738 case SMB2_OP_SESSSETUP:
1739 status = NT_STATUS_OK;
1740 break;
1741 default:
1742 break;
1745 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1746 switch (in_opcode) {
1747 case SMB2_OP_TCON:
1748 case SMB2_OP_CREATE:
1749 case SMB2_OP_GETINFO:
1750 case SMB2_OP_SETINFO:
1751 return NT_STATUS_INVALID_HANDLE;
1752 default:
1754 * Notice the check for
1755 * (session_info == NULL)
1756 * below.
1758 status = NT_STATUS_OK;
1759 break;
1762 if (!NT_STATUS_IS_OK(status)) {
1763 return status;
1766 session_info = session->global->auth_session_info;
1767 if (session_info == NULL) {
1768 return NT_STATUS_INVALID_HANDLE;
1771 set_current_user_info(session_info->unix_info->sanitized_username,
1772 session_info->unix_info->unix_name,
1773 session_info->info->domain_name);
1775 return NT_STATUS_OK;
1778 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1779 uint32_t data_length)
1781 uint16_t needed_charge;
1782 uint16_t credit_charge = 1;
1783 const uint8_t *inhdr;
1785 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1787 if (req->sconn->smb2.supports_multicredit) {
1788 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1789 credit_charge = MAX(credit_charge, 1);
1792 needed_charge = (data_length - 1)/ 65536 + 1;
1794 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1795 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1796 credit_charge, needed_charge));
1798 if (needed_charge > credit_charge) {
1799 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1800 credit_charge, needed_charge));
1801 return NT_STATUS_INVALID_PARAMETER;
1804 return NT_STATUS_OK;
1807 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1808 size_t expected_body_size)
1810 struct iovec *inhdr_v;
1811 const uint8_t *inhdr;
1812 uint16_t opcode;
1813 const uint8_t *inbody;
1814 size_t body_size;
1815 size_t min_dyn_size = expected_body_size & 0x00000001;
1816 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1819 * The following should be checked already.
1821 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1822 return NT_STATUS_INTERNAL_ERROR;
1824 if (req->current_idx > max_idx) {
1825 return NT_STATUS_INTERNAL_ERROR;
1828 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1829 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1830 return NT_STATUS_INTERNAL_ERROR;
1832 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1833 return NT_STATUS_INTERNAL_ERROR;
1836 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1837 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1839 switch (opcode) {
1840 case SMB2_OP_IOCTL:
1841 case SMB2_OP_GETINFO:
1842 min_dyn_size = 0;
1843 break;
1847 * Now check the expected body size,
1848 * where the last byte might be in the
1849 * dynamic section..
1851 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1852 return NT_STATUS_INVALID_PARAMETER;
1854 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1855 return NT_STATUS_INVALID_PARAMETER;
1858 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1860 body_size = SVAL(inbody, 0x00);
1861 if (body_size != expected_body_size) {
1862 return NT_STATUS_INVALID_PARAMETER;
1865 return NT_STATUS_OK;
1868 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1870 struct smbXsrv_connection *conn = req->sconn->conn;
1871 const struct smbd_smb2_dispatch_table *call = NULL;
1872 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1873 const uint8_t *inhdr;
1874 uint16_t opcode;
1875 uint32_t flags;
1876 uint64_t mid;
1877 NTSTATUS status;
1878 NTSTATUS session_status;
1879 uint32_t allowed_flags;
1880 NTSTATUS return_value;
1881 struct smbXsrv_session *x = NULL;
1882 bool signing_required = false;
1883 bool encryption_required = false;
1885 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1887 /* TODO: verify more things */
1889 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1890 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1891 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1892 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1893 smb2_opcode_name(opcode),
1894 (unsigned long long)mid));
1896 if (conn->protocol >= PROTOCOL_SMB2_02) {
1898 * once the protocol is negotiated
1899 * SMB2_OP_NEGPROT is not allowed anymore
1901 if (opcode == SMB2_OP_NEGPROT) {
1902 /* drop the connection */
1903 return NT_STATUS_INVALID_PARAMETER;
1905 } else {
1907 * if the protocol is not negotiated yet
1908 * only SMB2_OP_NEGPROT is allowed.
1910 if (opcode != SMB2_OP_NEGPROT) {
1911 /* drop the connection */
1912 return NT_STATUS_INVALID_PARAMETER;
1917 * Check if the client provided a valid session id,
1918 * if so smbd_smb2_request_check_session() calls
1919 * set_current_user_info().
1921 * As some command don't require a valid session id
1922 * we defer the check of the session_status
1924 session_status = smbd_smb2_request_check_session(req);
1925 x = req->session;
1926 if (x != NULL) {
1927 signing_required = x->global->signing_required;
1928 encryption_required = x->global->encryption_required;
1930 if (opcode == SMB2_OP_SESSSETUP &&
1931 x->global->channels[0].signing_key.length) {
1932 signing_required = true;
1936 req->do_signing = false;
1937 req->do_encryption = false;
1938 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1939 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1940 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1942 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1943 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1944 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1945 (unsigned long long)x->global->session_wire_id,
1946 (unsigned long long)tf_session_id));
1948 * TODO: windows allows this...
1949 * should we drop the connection?
1951 * For now we just return ACCESS_DENIED
1952 * (Windows clients never trigger this)
1953 * and wait for an update of [MS-SMB2].
1955 return smbd_smb2_request_error(req,
1956 NT_STATUS_ACCESS_DENIED);
1959 req->do_encryption = true;
1962 if (encryption_required && !req->do_encryption) {
1963 return smbd_smb2_request_error(req,
1964 NT_STATUS_ACCESS_DENIED);
1967 call = smbd_smb2_call(opcode);
1968 if (call == NULL) {
1969 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1972 allowed_flags = SMB2_HDR_FLAG_CHAINED |
1973 SMB2_HDR_FLAG_SIGNED |
1974 SMB2_HDR_FLAG_DFS;
1975 if (opcode == SMB2_OP_CANCEL) {
1976 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
1978 if ((flags & ~allowed_flags) != 0) {
1979 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1982 if (flags & SMB2_HDR_FLAG_CHAINED) {
1984 * This check is mostly for giving the correct error code
1985 * for compounded requests.
1987 if (!NT_STATUS_IS_OK(session_status)) {
1988 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1990 } else {
1991 req->compat_chain_fsp = NULL;
1994 if (req->do_encryption) {
1995 signing_required = false;
1996 } else if (flags & SMB2_HDR_FLAG_SIGNED) {
1997 DATA_BLOB signing_key;
1999 if (x == NULL) {
2000 return smbd_smb2_request_error(
2001 req, NT_STATUS_ACCESS_DENIED);
2004 signing_key = x->global->channels[0].signing_key;
2007 * If we have a signing key, we should
2008 * sign the response
2010 if (signing_key.length > 0) {
2011 req->do_signing = true;
2014 status = smb2_signing_check_pdu(signing_key,
2015 conn->protocol,
2016 SMBD_SMB2_IN_HDR_IOV(req),
2017 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 return smbd_smb2_request_error(req, status);
2023 * Now that we know the request was correctly signed
2024 * we have to sign the response too.
2026 req->do_signing = true;
2028 if (!NT_STATUS_IS_OK(session_status)) {
2029 return smbd_smb2_request_error(req, session_status);
2031 } else if (opcode == SMB2_OP_CANCEL) {
2032 /* Cancel requests are allowed to skip the signing */
2033 } else if (signing_required) {
2035 * If signing is required we try to sign
2036 * a possible error response
2038 req->do_signing = true;
2039 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2042 if (flags & SMB2_HDR_FLAG_CHAINED) {
2043 req->compound_related = true;
2046 if (call->need_session) {
2047 if (!NT_STATUS_IS_OK(session_status)) {
2048 return smbd_smb2_request_error(req, session_status);
2052 if (call->need_tcon) {
2053 SMB_ASSERT(call->need_session);
2056 * This call needs to be run as user.
2058 * smbd_smb2_request_check_tcon()
2059 * calls change_to_user() on success.
2061 status = smbd_smb2_request_check_tcon(req);
2062 if (!NT_STATUS_IS_OK(status)) {
2063 return smbd_smb2_request_error(req, status);
2065 if (req->tcon->global->encryption_required) {
2066 encryption_required = true;
2068 if (encryption_required && !req->do_encryption) {
2069 return smbd_smb2_request_error(req,
2070 NT_STATUS_ACCESS_DENIED);
2074 if (call->fileid_ofs != 0) {
2075 size_t needed = call->fileid_ofs + 16;
2076 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2077 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2078 uint64_t file_id_persistent;
2079 uint64_t file_id_volatile;
2080 struct files_struct *fsp;
2082 SMB_ASSERT(call->need_tcon);
2084 if (needed > body_size) {
2085 return smbd_smb2_request_error(req,
2086 NT_STATUS_INVALID_PARAMETER);
2089 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2090 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2092 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2093 if (fsp == NULL) {
2094 if (!call->allow_invalid_fileid) {
2095 return smbd_smb2_request_error(req,
2096 NT_STATUS_FILE_CLOSED);
2099 if (file_id_persistent != UINT64_MAX) {
2100 return smbd_smb2_request_error(req,
2101 NT_STATUS_FILE_CLOSED);
2103 if (file_id_volatile != UINT64_MAX) {
2104 return smbd_smb2_request_error(req,
2105 NT_STATUS_FILE_CLOSED);
2110 if (call->as_root) {
2111 SMB_ASSERT(call->fileid_ofs == 0);
2112 /* This call needs to be run as root */
2113 change_to_root_user();
2114 } else {
2115 SMB_ASSERT(call->need_tcon);
2118 switch (opcode) {
2119 case SMB2_OP_NEGPROT:
2121 START_PROFILE(smb2_negprot);
2122 return_value = smbd_smb2_request_process_negprot(req);
2123 END_PROFILE(smb2_negprot);
2125 break;
2127 case SMB2_OP_SESSSETUP:
2129 START_PROFILE(smb2_sesssetup);
2130 return_value = smbd_smb2_request_process_sesssetup(req);
2131 END_PROFILE(smb2_sesssetup);
2133 break;
2135 case SMB2_OP_LOGOFF:
2137 START_PROFILE(smb2_logoff);
2138 return_value = smbd_smb2_request_process_logoff(req);
2139 END_PROFILE(smb2_logoff);
2141 break;
2143 case SMB2_OP_TCON:
2145 START_PROFILE(smb2_tcon);
2146 return_value = smbd_smb2_request_process_tcon(req);
2147 END_PROFILE(smb2_tcon);
2149 break;
2151 case SMB2_OP_TDIS:
2153 START_PROFILE(smb2_tdis);
2154 return_value = smbd_smb2_request_process_tdis(req);
2155 END_PROFILE(smb2_tdis);
2157 break;
2159 case SMB2_OP_CREATE:
2161 START_PROFILE(smb2_create);
2162 return_value = smbd_smb2_request_process_create(req);
2163 END_PROFILE(smb2_create);
2165 break;
2167 case SMB2_OP_CLOSE:
2169 START_PROFILE(smb2_close);
2170 return_value = smbd_smb2_request_process_close(req);
2171 END_PROFILE(smb2_close);
2173 break;
2175 case SMB2_OP_FLUSH:
2177 START_PROFILE(smb2_flush);
2178 return_value = smbd_smb2_request_process_flush(req);
2179 END_PROFILE(smb2_flush);
2181 break;
2183 case SMB2_OP_READ:
2185 START_PROFILE(smb2_read);
2186 return_value = smbd_smb2_request_process_read(req);
2187 END_PROFILE(smb2_read);
2189 break;
2191 case SMB2_OP_WRITE:
2193 START_PROFILE(smb2_write);
2194 return_value = smbd_smb2_request_process_write(req);
2195 END_PROFILE(smb2_write);
2197 break;
2199 case SMB2_OP_LOCK:
2201 START_PROFILE(smb2_lock);
2202 return_value = smbd_smb2_request_process_lock(req);
2203 END_PROFILE(smb2_lock);
2205 break;
2207 case SMB2_OP_IOCTL:
2209 START_PROFILE(smb2_ioctl);
2210 return_value = smbd_smb2_request_process_ioctl(req);
2211 END_PROFILE(smb2_ioctl);
2213 break;
2215 case SMB2_OP_CANCEL:
2217 START_PROFILE(smb2_cancel);
2218 return_value = smbd_smb2_request_process_cancel(req);
2219 END_PROFILE(smb2_cancel);
2221 break;
2223 case SMB2_OP_KEEPALIVE:
2225 START_PROFILE(smb2_keepalive);
2226 return_value = smbd_smb2_request_process_keepalive(req);
2227 END_PROFILE(smb2_keepalive);
2229 break;
2231 case SMB2_OP_FIND:
2233 START_PROFILE(smb2_find);
2234 return_value = smbd_smb2_request_process_find(req);
2235 END_PROFILE(smb2_find);
2237 break;
2239 case SMB2_OP_NOTIFY:
2241 START_PROFILE(smb2_notify);
2242 return_value = smbd_smb2_request_process_notify(req);
2243 END_PROFILE(smb2_notify);
2245 break;
2247 case SMB2_OP_GETINFO:
2249 START_PROFILE(smb2_getinfo);
2250 return_value = smbd_smb2_request_process_getinfo(req);
2251 END_PROFILE(smb2_getinfo);
2253 break;
2255 case SMB2_OP_SETINFO:
2257 START_PROFILE(smb2_setinfo);
2258 return_value = smbd_smb2_request_process_setinfo(req);
2259 END_PROFILE(smb2_setinfo);
2261 break;
2263 case SMB2_OP_BREAK:
2265 START_PROFILE(smb2_break);
2266 return_value = smbd_smb2_request_process_break(req);
2267 END_PROFILE(smb2_break);
2269 break;
2271 default:
2272 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2273 break;
2275 return return_value;
2278 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2280 struct smbXsrv_connection *conn = req->sconn->conn;
2281 struct tevent_req *subreq;
2282 int first_idx = 1;
2283 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2284 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2285 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2287 req->subreq = NULL;
2288 TALLOC_FREE(req->async_te);
2290 if (req->do_encryption &&
2291 (firsttf->iov_len == 0) &&
2292 (req->first_key.length == 0) &&
2293 (req->session != NULL) &&
2294 (req->session->global->encryption_key.length != 0))
2296 DATA_BLOB encryption_key = req->session->global->encryption_key;
2297 uint8_t *tf;
2298 uint64_t session_id = req->session->global->session_wire_id;
2299 struct smbXsrv_session *x = req->session;
2300 uint64_t nonce_high;
2301 uint64_t nonce_low;
2303 nonce_high = x->nonce_high;
2304 nonce_low = x->nonce_low;
2306 x->nonce_low += 1;
2307 if (x->nonce_low == 0) {
2308 x->nonce_low += 1;
2309 x->nonce_high += 1;
2313 * We need to place the SMB2_TRANSFORM header before the
2314 * first SMB2 header
2318 * we need to remember the encryption key
2319 * and defer the signing/encryption until
2320 * we are sure that we do not change
2321 * the header again.
2323 req->first_key = data_blob_dup_talloc(req, encryption_key);
2324 if (req->first_key.data == NULL) {
2325 return NT_STATUS_NO_MEMORY;
2328 tf = talloc_zero_array(req->out.vector, uint8_t,
2329 SMB2_TF_HDR_SIZE);
2330 if (tf == NULL) {
2331 return NT_STATUS_NO_MEMORY;
2334 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2335 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2336 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2337 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2339 firsttf->iov_base = (void *)tf;
2340 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2343 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2344 (req->last_key.length > 0) &&
2345 (firsttf->iov_len == 0))
2347 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2348 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2349 NTSTATUS status;
2352 * As we are sure the header of the last request in the
2353 * compound chain will not change, we can to sign here
2354 * with the last signing key we remembered.
2356 status = smb2_signing_sign_pdu(req->last_key,
2357 conn->protocol,
2358 lasthdr,
2359 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2360 if (!NT_STATUS_IS_OK(status)) {
2361 return status;
2364 data_blob_clear_free(&req->last_key);
2366 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2368 if (req->current_idx < req->out.vector_count) {
2370 * We must process the remaining compound
2371 * SMB2 requests before any new incoming SMB2
2372 * requests. This is because incoming SMB2
2373 * requests may include a cancel for a
2374 * compound request we haven't processed
2375 * yet.
2377 struct tevent_immediate *im = tevent_create_immediate(req);
2378 if (!im) {
2379 return NT_STATUS_NO_MEMORY;
2382 if (req->do_signing && firsttf->iov_len == 0) {
2383 struct smbXsrv_session *x = req->session;
2384 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2387 * we need to remember the signing key
2388 * and defer the signing until
2389 * we are sure that we do not change
2390 * the header again.
2392 req->last_key = data_blob_dup_talloc(req, signing_key);
2393 if (req->last_key.data == NULL) {
2394 return NT_STATUS_NO_MEMORY;
2398 tevent_schedule_immediate(im,
2399 req->sconn->ev_ctx,
2400 smbd_smb2_request_dispatch_immediate,
2401 req);
2402 return NT_STATUS_OK;
2405 if (req->compound_related) {
2406 req->compound_related = false;
2409 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2411 /* Set credit for these operations (zero credits if this
2412 is a final reply for an async operation). */
2413 smb2_calculate_credits(req, req);
2416 * now check if we need to sign the current response
2418 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2419 NTSTATUS status;
2421 status = smb2_signing_encrypt_pdu(req->first_key,
2422 conn->protocol,
2423 firsttf,
2424 req->out.vector_count - first_idx);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 return status;
2428 } else if (req->do_signing) {
2429 NTSTATUS status;
2430 struct smbXsrv_session *x = req->session;
2431 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2433 status = smb2_signing_sign_pdu(signing_key,
2434 conn->protocol,
2435 outhdr,
2436 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 return status;
2441 data_blob_clear_free(&req->first_key);
2443 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2444 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2445 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2446 /* Dynamic part is NULL. Chop it off,
2447 We're going to send it via sendfile. */
2448 req->out.vector_count -= 1;
2451 subreq = tstream_writev_queue_send(req,
2452 req->sconn->ev_ctx,
2453 req->sconn->smb2.stream,
2454 req->sconn->smb2.send_queue,
2455 req->out.vector,
2456 req->out.vector_count);
2457 if (subreq == NULL) {
2458 return NT_STATUS_NO_MEMORY;
2460 tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
2462 * We're done with this request -
2463 * move it off the "being processed" queue.
2465 DLIST_REMOVE(req->sconn->smb2.requests, req);
2467 return NT_STATUS_OK;
2470 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2472 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2473 struct tevent_immediate *im,
2474 void *private_data)
2476 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2477 struct smbd_smb2_request);
2478 struct smbd_server_connection *sconn = req->sconn;
2479 NTSTATUS status;
2481 TALLOC_FREE(im);
2483 if (DEBUGLEVEL >= 10) {
2484 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2485 req->current_idx, req->in.vector_count));
2486 print_req_vectors(req);
2489 status = smbd_smb2_request_dispatch(req);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 smbd_server_connection_terminate(sconn, nt_errstr(status));
2492 return;
2495 status = smbd_smb2_request_next_incoming(sconn);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 smbd_server_connection_terminate(sconn, nt_errstr(status));
2498 return;
2502 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
2504 struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
2505 struct smbd_smb2_request);
2506 struct smbd_server_connection *sconn = req->sconn;
2507 int ret;
2508 int sys_errno;
2509 NTSTATUS status;
2511 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2512 TALLOC_FREE(subreq);
2513 TALLOC_FREE(req);
2514 if (ret == -1) {
2515 status = map_nt_error_from_unix(sys_errno);
2516 DEBUG(2,("smbd_smb2_request_writev_done: client write error %s\n",
2517 nt_errstr(status)));
2518 smbd_server_connection_terminate(sconn, nt_errstr(status));
2519 return;
2522 status = smbd_smb2_request_next_incoming(sconn);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 smbd_server_connection_terminate(sconn, nt_errstr(status));
2525 return;
2529 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2530 NTSTATUS status,
2531 DATA_BLOB body, DATA_BLOB *dyn,
2532 const char *location)
2534 uint8_t *outhdr;
2535 struct iovec *outbody_v;
2536 struct iovec *outdyn_v;
2537 uint32_t next_command_ofs;
2539 DEBUG(10,("smbd_smb2_request_done_ex: "
2540 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2541 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2542 dyn ? "yes": "no",
2543 (unsigned int)(dyn ? dyn->length : 0),
2544 location));
2546 if (body.length < 2) {
2547 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2550 if ((body.length % 2) != 0) {
2551 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2554 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2555 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2556 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2558 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2559 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2561 outbody_v->iov_base = (void *)body.data;
2562 outbody_v->iov_len = body.length;
2564 if (dyn) {
2565 outdyn_v->iov_base = (void *)dyn->data;
2566 outdyn_v->iov_len = dyn->length;
2567 } else {
2568 outdyn_v->iov_base = NULL;
2569 outdyn_v->iov_len = 0;
2572 /* see if we need to recalculate the offset to the next response */
2573 if (next_command_ofs > 0) {
2574 next_command_ofs = SMB2_HDR_BODY;
2575 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2576 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2579 if ((next_command_ofs % 8) != 0) {
2580 size_t pad_size = 8 - (next_command_ofs % 8);
2581 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2583 * if the dyn buffer is empty
2584 * we can use it to add padding
2586 uint8_t *pad;
2588 pad = talloc_zero_array(req->out.vector,
2589 uint8_t, pad_size);
2590 if (pad == NULL) {
2591 return smbd_smb2_request_error(req,
2592 NT_STATUS_NO_MEMORY);
2595 outdyn_v->iov_base = (void *)pad;
2596 outdyn_v->iov_len = pad_size;
2597 } else {
2599 * For now we copy the dynamic buffer
2600 * and add the padding to the new buffer
2602 size_t old_size;
2603 uint8_t *old_dyn;
2604 size_t new_size;
2605 uint8_t *new_dyn;
2607 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2608 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2610 new_size = old_size + pad_size;
2611 new_dyn = talloc_zero_array(req->out.vector,
2612 uint8_t, new_size);
2613 if (new_dyn == NULL) {
2614 return smbd_smb2_request_error(req,
2615 NT_STATUS_NO_MEMORY);
2618 memcpy(new_dyn, old_dyn, old_size);
2619 memset(new_dyn + old_size, 0, pad_size);
2621 outdyn_v->iov_base = (void *)new_dyn;
2622 outdyn_v->iov_len = new_size;
2624 next_command_ofs += pad_size;
2627 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2629 return smbd_smb2_request_reply(req);
2632 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2633 NTSTATUS status,
2634 DATA_BLOB *info,
2635 const char *location)
2637 DATA_BLOB body;
2638 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2639 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2641 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2642 req->current_idx, nt_errstr(status), info ? " +info" : "",
2643 location));
2645 if (unread_bytes) {
2646 /* Recvfile error. Drain incoming socket. */
2647 size_t ret = drain_socket(req->sconn->sock, unread_bytes);
2648 if (ret != unread_bytes) {
2649 smbd_server_connection_terminate(req->sconn,
2650 "Failed to drain SMB2 socket\n");
2654 body.data = outhdr + SMB2_HDR_BODY;
2655 body.length = 8;
2656 SSVAL(body.data, 0, 9);
2658 if (info) {
2659 SIVAL(body.data, 0x04, info->length);
2660 } else {
2661 /* Allocated size of req->out.vector[i].iov_base
2662 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2663 * 1 byte without having to do an alloc.
2665 info = talloc_zero_array(req->out.vector,
2666 DATA_BLOB,
2668 if (!info) {
2669 return NT_STATUS_NO_MEMORY;
2671 info->data = ((uint8_t *)outhdr) +
2672 OUTVEC_ALLOC_SIZE - 1;
2673 info->length = 1;
2674 SCVAL(info->data, 0, 0);
2678 * Note: Even if there is an error, continue to process the request.
2679 * per MS-SMB2.
2682 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2686 struct smbd_smb2_send_oplock_break_state {
2687 struct smbd_server_connection *sconn;
2688 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2689 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2692 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
2694 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2695 struct smbXsrv_session *session,
2696 struct smbXsrv_tcon *tcon,
2697 struct smbXsrv_open *op,
2698 uint8_t oplock_level)
2700 struct smbd_smb2_send_oplock_break_state *state;
2701 struct smbXsrv_connection *conn = sconn->conn;
2702 struct tevent_req *subreq;
2703 uint8_t *tf;
2704 size_t tf_len;
2705 uint8_t *hdr;
2706 uint8_t *body;
2707 size_t body_len;
2708 uint8_t *dyn;
2709 size_t dyn_len;
2710 bool do_encryption = session->global->encryption_required;
2711 uint64_t nonce_high = 0;
2712 uint64_t nonce_low = 0;
2714 if (tcon->global->encryption_required) {
2715 do_encryption = true;
2718 state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
2719 if (state == NULL) {
2720 return NT_STATUS_NO_MEMORY;
2722 state->sconn = sconn;
2724 tf = state->buf + NBT_HDR_SIZE;
2725 tf_len = SMB2_TF_HDR_SIZE;
2726 hdr = tf + tf_len;
2727 body = hdr + SMB2_HDR_BODY;
2728 body_len = 0x18;
2729 dyn = body + body_len;
2730 dyn_len = 0;
2732 if (do_encryption) {
2733 nonce_high = session->nonce_high;
2734 nonce_low = session->nonce_low;
2736 session->nonce_low += 1;
2737 if (session->nonce_low == 0) {
2738 session->nonce_low += 1;
2739 session->nonce_high += 1;
2743 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2744 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2745 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2746 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2748 SIVAL(hdr, 0, SMB2_MAGIC);
2749 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2750 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2751 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2752 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2753 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2754 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2755 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2756 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2757 SIVAL(hdr, SMB2_HDR_PID, 0);
2758 SIVAL(hdr, SMB2_HDR_TID, 0);
2759 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2760 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2762 SSVAL(body, 0x00, body_len);
2764 SCVAL(body, 0x02, oplock_level);
2765 SCVAL(body, 0x03, 0); /* reserved */
2766 SIVAL(body, 0x04, 0); /* reserved */
2767 SBVAL(body, 0x08, op->global->open_persistent_id);
2768 SBVAL(body, 0x10, op->global->open_volatile_id);
2770 state->vector[0].iov_base = (void *)state->buf;
2771 state->vector[0].iov_len = NBT_HDR_SIZE;
2773 if (do_encryption) {
2774 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2775 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2776 } else {
2777 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2778 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2781 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2782 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2784 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2785 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2787 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2788 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2790 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2792 if (do_encryption) {
2793 NTSTATUS status;
2794 DATA_BLOB encryption_key = session->global->encryption_key;
2796 status = smb2_signing_encrypt_pdu(encryption_key,
2797 conn->protocol,
2798 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2799 SMBD_SMB2_NUM_IOV_PER_REQ);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 return status;
2805 subreq = tstream_writev_queue_send(state,
2806 sconn->ev_ctx,
2807 sconn->smb2.stream,
2808 sconn->smb2.send_queue,
2809 state->vector,
2810 ARRAY_SIZE(state->vector));
2811 if (subreq == NULL) {
2812 return NT_STATUS_NO_MEMORY;
2814 tevent_req_set_callback(subreq,
2815 smbd_smb2_oplock_break_writev_done,
2816 state);
2818 return NT_STATUS_OK;
2821 static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
2823 struct smbd_smb2_send_oplock_break_state *state =
2824 tevent_req_callback_data(subreq,
2825 struct smbd_smb2_send_oplock_break_state);
2826 struct smbd_server_connection *sconn = state->sconn;
2827 int ret;
2828 int sys_errno;
2830 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2831 TALLOC_FREE(subreq);
2832 if (ret == -1) {
2833 NTSTATUS status = map_nt_error_from_unix(sys_errno);
2834 smbd_server_connection_terminate(sconn, nt_errstr(status));
2835 return;
2838 TALLOC_FREE(state);
2841 struct smbd_smb2_request_read_state {
2842 struct tevent_context *ev;
2843 struct smbd_server_connection *sconn;
2844 struct smbd_smb2_request *smb2_req;
2845 struct {
2846 uint8_t nbt[NBT_HDR_SIZE];
2847 bool done;
2848 } hdr;
2849 bool doing_receivefile;
2850 size_t min_recv_size;
2851 size_t pktlen;
2852 uint8_t *pktbuf;
2855 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2856 void *private_data,
2857 TALLOC_CTX *mem_ctx,
2858 struct iovec **_vector,
2859 size_t *_count);
2860 static void smbd_smb2_request_read_done(struct tevent_req *subreq);
2862 static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
2864 if (smb2_req->do_signing) {
2865 return 0;
2867 if (smb2_req->do_encryption) {
2868 return 0;
2870 return (size_t)lp_min_receive_file_size();
2873 static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
2874 struct tevent_context *ev,
2875 struct smbd_server_connection *sconn)
2877 struct tevent_req *req;
2878 struct smbd_smb2_request_read_state *state;
2879 struct tevent_req *subreq;
2881 req = tevent_req_create(mem_ctx, &state,
2882 struct smbd_smb2_request_read_state);
2883 if (req == NULL) {
2884 return NULL;
2886 state->ev = ev;
2887 state->sconn = sconn;
2889 state->smb2_req = smbd_smb2_request_allocate(state);
2890 if (tevent_req_nomem(state->smb2_req, req)) {
2891 return tevent_req_post(req, ev);
2893 state->smb2_req->sconn = sconn;
2894 state->min_recv_size = get_min_receive_file_size(state->smb2_req);
2896 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
2897 state->ev,
2898 state->sconn->smb2.stream,
2899 state->sconn->smb2.recv_queue,
2900 smbd_smb2_request_next_vector,
2901 state);
2902 if (tevent_req_nomem(subreq, req)) {
2903 return tevent_req_post(req, ev);
2905 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
2907 return req;
2910 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2912 uint32_t flags;
2914 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2915 /* Transform header. Cannot recvfile. */
2916 return false;
2918 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2919 /* Not SMB2. Normal error path will cope. */
2920 return false;
2922 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2923 /* Not SMB2. Normal error path will cope. */
2924 return false;
2926 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2927 /* Needs to be a WRITE. */
2928 return false;
2930 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2931 /* Chained. Cannot recvfile. */
2932 return false;
2934 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2935 if (flags & SMB2_HDR_FLAG_CHAINED) {
2936 /* Chained. Cannot recvfile. */
2937 return false;
2939 if (flags & SMB2_HDR_FLAG_SIGNED) {
2940 /* Signed. Cannot recvfile. */
2941 return false;
2944 DEBUG(10,("Doing recvfile write len = %u\n",
2945 (unsigned int)(state->pktlen -
2946 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
2948 return true;
2951 static int smbd_smb2_request_next_vector(struct tstream_context *stream,
2952 void *private_data,
2953 TALLOC_CTX *mem_ctx,
2954 struct iovec **_vector,
2955 size_t *_count)
2957 struct smbd_smb2_request_read_state *state =
2958 talloc_get_type_abort(private_data,
2959 struct smbd_smb2_request_read_state);
2960 struct iovec *vector = NULL;
2961 size_t min_recvfile_size = UINT32_MAX;
2963 if (state->pktlen > 0) {
2964 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
2966 * Not a possible receivefile write.
2967 * Read the rest of the data.
2969 state->doing_receivefile = false;
2970 vector = talloc_array(mem_ctx, struct iovec, 1);
2971 if (vector == NULL) {
2972 return -1;
2974 vector[0].iov_base = (void *)(state->pktbuf +
2975 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2976 vector[0].iov_len = (state->pktlen -
2977 SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
2978 *_vector = vector;
2979 *_count = 1;
2980 } else {
2982 * Either this is a receivefile write so we've
2983 * done a short read, or if not we have all the data.
2984 * Either way, we're done and
2985 * smbd_smb2_request_read_done() will handle
2986 * and short read case by looking at the
2987 * state->doing_receivefile value.
2989 *_vector = NULL;
2990 *_count = 0;
2992 return 0;
2995 if (!state->hdr.done) {
2997 * first we need to get the NBT header
2999 vector = talloc_array(mem_ctx, struct iovec, 1);
3000 if (vector == NULL) {
3001 return -1;
3004 vector[0].iov_base = (void *)state->hdr.nbt;
3005 vector[0].iov_len = NBT_HDR_SIZE;
3007 *_vector = vector;
3008 *_count = 1;
3010 state->hdr.done = true;
3011 return 0;
3015 * Now we analyze the NBT header
3017 state->pktlen = smb2_len(state->hdr.nbt);
3019 if (state->pktlen == 0) {
3020 /* if there're no remaining bytes, we're done */
3021 *_vector = NULL;
3022 *_count = 0;
3023 return 0;
3026 state->pktbuf = talloc_array(state->smb2_req, uint8_t, state->pktlen);
3027 if (state->pktbuf == NULL) {
3028 return -1;
3031 vector = talloc_array(mem_ctx, struct iovec, 1);
3032 if (vector == NULL) {
3033 return -1;
3036 vector[0].iov_base = (void *)state->pktbuf;
3038 if (state->min_recv_size != 0) {
3039 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3040 min_recvfile_size += state->min_recv_size;
3043 if (state->pktlen > min_recvfile_size) {
3045 * Might be a receivefile write. Read the SMB2 HEADER +
3046 * SMB2_WRITE header first. Set 'doing_receivefile'
3047 * as we're *attempting* receivefile write. If this
3048 * turns out not to be a SMB2_WRITE request or otherwise
3049 * not suitable then we'll just read the rest of the data
3050 * the next time this function is called.
3052 vector[0].iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3053 state->doing_receivefile = true;
3054 } else {
3055 vector[0].iov_len = state->pktlen;
3058 *_vector = vector;
3059 *_count = 1;
3060 return 0;
3063 static void smbd_smb2_request_read_done(struct tevent_req *subreq)
3065 struct tevent_req *req =
3066 tevent_req_callback_data(subreq,
3067 struct tevent_req);
3068 struct smbd_smb2_request_read_state *state =
3069 tevent_req_data(req,
3070 struct smbd_smb2_request_read_state);
3071 int ret;
3072 int sys_errno;
3073 NTSTATUS status;
3074 NTTIME now;
3076 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
3077 TALLOC_FREE(subreq);
3078 if (ret == -1) {
3079 status = map_nt_error_from_unix(sys_errno);
3080 tevent_req_nterror(req, status);
3081 return;
3084 if (state->hdr.nbt[0] != 0x00) {
3085 DEBUG(1,("smbd_smb2_request_read_done: ignore NBT[0x%02X] msg\n",
3086 state->hdr.nbt[0]));
3088 ZERO_STRUCT(state->hdr);
3089 TALLOC_FREE(state->pktbuf);
3090 state->pktlen = 0;
3092 subreq = tstream_readv_pdu_queue_send(state->smb2_req,
3093 state->ev,
3094 state->sconn->smb2.stream,
3095 state->sconn->smb2.recv_queue,
3096 smbd_smb2_request_next_vector,
3097 state);
3098 if (tevent_req_nomem(subreq, req)) {
3099 return;
3101 tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
3102 return;
3105 state->smb2_req->request_time = timeval_current();
3106 now = timeval_to_nttime(&state->smb2_req->request_time);
3108 status = smbd_smb2_inbuf_parse_compound(state->smb2_req->sconn->conn,
3109 now,
3110 state->pktbuf,
3111 state->pktlen,
3112 state->smb2_req,
3113 &state->smb2_req->in.vector,
3114 &state->smb2_req->in.vector_count);
3115 if (tevent_req_nterror(req, status)) {
3116 return;
3119 if (state->doing_receivefile) {
3120 state->smb2_req->smb1req = talloc_zero(state->smb2_req,
3121 struct smb_request);
3122 if (tevent_req_nomem(state->smb2_req->smb1req, req)) {
3123 return;
3125 state->smb2_req->smb1req->unread_bytes =
3126 state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3129 state->smb2_req->current_idx = 1;
3131 tevent_req_done(req);
3134 static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
3135 TALLOC_CTX *mem_ctx,
3136 struct smbd_smb2_request **_smb2_req)
3138 struct smbd_smb2_request_read_state *state =
3139 tevent_req_data(req,
3140 struct smbd_smb2_request_read_state);
3141 NTSTATUS status;
3143 if (tevent_req_is_nterror(req, &status)) {
3144 tevent_req_received(req);
3145 return status;
3148 *_smb2_req = talloc_move(mem_ctx, &state->smb2_req);
3149 tevent_req_received(req);
3150 return NT_STATUS_OK;
3153 static void smbd_smb2_request_incoming(struct tevent_req *subreq);
3155 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
3157 size_t max_send_queue_len;
3158 size_t cur_send_queue_len;
3159 struct tevent_req *subreq;
3161 if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
3163 * if there is already a smbd_smb2_request_read
3164 * pending, we are done.
3166 return NT_STATUS_OK;
3169 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
3170 cur_send_queue_len = tevent_queue_length(sconn->smb2.send_queue);
3172 if (cur_send_queue_len > max_send_queue_len) {
3174 * if we have a lot of requests to send,
3175 * we wait until they are on the wire until we
3176 * ask for the next request.
3178 return NT_STATUS_OK;
3181 /* ask for the next request */
3182 subreq = smbd_smb2_request_read_send(sconn, sconn->ev_ctx, sconn);
3183 if (subreq == NULL) {
3184 return NT_STATUS_NO_MEMORY;
3186 tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
3188 return NT_STATUS_OK;
3191 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3192 uint8_t *inbuf, size_t size)
3194 NTSTATUS status;
3195 struct smbd_smb2_request *req = NULL;
3197 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3198 (unsigned int)size));
3200 status = smbd_initialize_smb2(sconn);
3201 if (!NT_STATUS_IS_OK(status)) {
3202 smbd_server_connection_terminate(sconn, nt_errstr(status));
3203 return;
3206 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3207 if (!NT_STATUS_IS_OK(status)) {
3208 smbd_server_connection_terminate(sconn, nt_errstr(status));
3209 return;
3212 status = smbd_smb2_request_validate(req);
3213 if (!NT_STATUS_IS_OK(status)) {
3214 smbd_server_connection_terminate(sconn, nt_errstr(status));
3215 return;
3218 status = smbd_smb2_request_setup_out(req);
3219 if (!NT_STATUS_IS_OK(status)) {
3220 smbd_server_connection_terminate(sconn, nt_errstr(status));
3221 return;
3224 status = smbd_smb2_request_dispatch(req);
3225 if (!NT_STATUS_IS_OK(status)) {
3226 smbd_server_connection_terminate(sconn, nt_errstr(status));
3227 return;
3230 status = smbd_smb2_request_next_incoming(sconn);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 smbd_server_connection_terminate(sconn, nt_errstr(status));
3233 return;
3236 sconn->num_requests++;
3239 static void smbd_smb2_request_incoming(struct tevent_req *subreq)
3241 struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
3242 struct smbd_server_connection);
3243 NTSTATUS status;
3244 struct smbd_smb2_request *req = NULL;
3246 status = smbd_smb2_request_read_recv(subreq, sconn, &req);
3247 TALLOC_FREE(subreq);
3248 if (!NT_STATUS_IS_OK(status)) {
3249 DEBUG(2,("smbd_smb2_request_incoming: client read error %s\n",
3250 nt_errstr(status)));
3251 smbd_server_connection_terminate(sconn, nt_errstr(status));
3252 return;
3255 DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
3256 req->current_idx, req->in.vector_count));
3258 status = smbd_smb2_request_validate(req);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 smbd_server_connection_terminate(sconn, nt_errstr(status));
3261 return;
3264 status = smbd_smb2_request_setup_out(req);
3265 if (!NT_STATUS_IS_OK(status)) {
3266 smbd_server_connection_terminate(sconn, nt_errstr(status));
3267 return;
3270 status = smbd_smb2_request_dispatch(req);
3271 if (!NT_STATUS_IS_OK(status)) {
3272 smbd_server_connection_terminate(sconn, nt_errstr(status));
3273 return;
3276 status = smbd_smb2_request_next_incoming(sconn);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 smbd_server_connection_terminate(sconn, nt_errstr(status));
3279 return;
3282 sconn->num_requests++;
3284 /* The timeout_processing function isn't run nearly
3285 often enough to implement 'max log size' without
3286 overrunning the size of the file by many megabytes.
3287 This is especially true if we are running at debug
3288 level 10. Checking every 50 SMB2s is a nice
3289 tradeoff of performance vs log file size overrun. */
3291 if ((sconn->num_requests % 50) == 0 &&
3292 need_to_check_log_size()) {
3293 change_to_root_user();
3294 check_log_size();