s3:smb2_server: move sconn->smb2.send_queue* to xconn->smb2.send_queue*
[Samba.git] / source3 / smbd / smb2_server.c
blobba0091103b73636f1a5587b86012a99f999866ce
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 struct smbXsrv_connection *xconn = sconn->conn;
205 TALLOC_FREE(xconn->transport.fde);
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 xconn->transport.fde = tevent_add_fd(sconn->ev_ctx,
218 sconn,
219 xconn->transport.sock,
220 TEVENT_FD_READ,
221 smbd_smb2_connection_handler,
222 sconn);
223 if (xconn->transport.fde == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(xconn->transport.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(conn->smb2.send_queue, &nreq->queue_entry, NULL);
1265 conn->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 smbXsrv_connection *xconn = sconn->conn;
1426 struct smbd_smb2_request_pending_state *state = NULL;
1427 uint8_t *outhdr = NULL;
1428 const uint8_t *inhdr = NULL;
1429 uint8_t *tf = NULL;
1430 size_t tf_len = 0;
1431 uint8_t *hdr = NULL;
1432 uint8_t *body = NULL;
1433 uint8_t *dyn = NULL;
1434 uint32_t flags = 0;
1435 uint64_t session_id = 0;
1436 uint64_t message_id = 0;
1437 uint64_t nonce_high = 0;
1438 uint64_t nonce_low = 0;
1439 uint64_t async_id = 0;
1440 NTSTATUS status;
1442 TALLOC_FREE(req->async_te);
1444 /* Ensure our final reply matches the interim one. */
1445 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1446 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1447 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1448 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1449 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1451 async_id = message_id; /* keep it simple for now... */
1453 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1454 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1456 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1457 "going async\n",
1458 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1459 (unsigned long long)async_id ));
1462 * What we send is identical to a smbd_smb2_request_error
1463 * packet with an error status of STATUS_PENDING. Make use
1464 * of this fact sometime when refactoring. JRA.
1467 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1468 if (state == NULL) {
1469 smbd_server_connection_terminate(req->sconn,
1470 nt_errstr(NT_STATUS_NO_MEMORY));
1471 return;
1473 state->sconn = req->sconn;
1475 tf = state->buf + NBT_HDR_SIZE;
1476 tf_len = SMB2_TF_HDR_SIZE;
1478 hdr = tf + SMB2_TF_HDR_SIZE;
1479 body = hdr + SMB2_HDR_BODY;
1480 dyn = body + 8;
1482 if (req->do_encryption) {
1483 struct smbXsrv_session *x = req->session;
1485 nonce_high = x->nonce_high;
1486 nonce_low = x->nonce_low;
1488 x->nonce_low += 1;
1489 if (x->nonce_low == 0) {
1490 x->nonce_low += 1;
1491 x->nonce_high += 1;
1495 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1496 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1497 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1498 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1500 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1501 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1502 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1503 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1504 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1506 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1507 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1508 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1509 SBVAL(hdr, SMB2_HDR_PID, async_id);
1510 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1511 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1512 memcpy(hdr+SMB2_HDR_SIGNATURE,
1513 outhdr+SMB2_HDR_SIGNATURE, 16);
1515 SSVAL(body, 0x00, 0x08 + 1);
1517 SCVAL(body, 0x02, 0);
1518 SCVAL(body, 0x03, 0);
1519 SIVAL(body, 0x04, 0);
1520 /* Match W2K8R2... */
1521 SCVAL(dyn, 0x00, 0x21);
1523 state->vector[0].iov_base = (void *)state->buf;
1524 state->vector[0].iov_len = NBT_HDR_SIZE;
1526 if (req->do_encryption) {
1527 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1528 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1529 } else {
1530 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1531 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1534 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1535 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1537 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1538 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1540 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1541 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1543 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1545 /* Ensure we correctly go through crediting. Grant
1546 the credits now, and zero credits on the final
1547 response. */
1548 smb2_set_operation_credit(req->sconn,
1549 SMBD_SMB2_IN_HDR_IOV(req),
1550 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1552 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1554 if (DEBUGLVL(10)) {
1555 int i;
1557 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1558 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1559 (unsigned int)i,
1560 (unsigned int)ARRAY_SIZE(state->vector),
1561 (unsigned int)state->vector[i].iov_len);
1565 if (req->do_encryption) {
1566 struct smbXsrv_session *x = req->session;
1567 DATA_BLOB encryption_key = x->global->encryption_key;
1569 status = smb2_signing_encrypt_pdu(encryption_key,
1570 xconn->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 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1582 status = smb2_signing_sign_pdu(signing_key,
1583 xconn->protocol,
1584 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1585 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1586 if (!NT_STATUS_IS_OK(status)) {
1587 smbd_server_connection_terminate(req->sconn,
1588 nt_errstr(status));
1589 return;
1593 state->queue_entry.mem_ctx = state;
1594 state->queue_entry.vector = state->vector;
1595 state->queue_entry.count = ARRAY_SIZE(state->vector);
1596 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1597 xconn->smb2.send_queue_len++;
1599 status = smbd_smb2_flush_send_queue(sconn);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 smbd_server_connection_terminate(sconn,
1602 nt_errstr(status));
1603 return;
1607 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1609 struct smbd_server_connection *sconn = req->sconn;
1610 struct smbd_smb2_request *cur;
1611 const uint8_t *inhdr;
1612 uint32_t flags;
1613 uint64_t search_message_id;
1614 uint64_t search_async_id;
1615 uint64_t found_id;
1617 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1619 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1620 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1621 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1624 * we don't need the request anymore
1625 * cancel requests never have a response
1627 DLIST_REMOVE(req->sconn->smb2.requests, req);
1628 TALLOC_FREE(req);
1630 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1631 const uint8_t *outhdr;
1632 uint64_t message_id;
1633 uint64_t async_id;
1635 if (cur->compound_related) {
1637 * Never cancel anything in a compound request.
1638 * Way too hard to deal with the result.
1640 continue;
1643 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1645 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1646 async_id = BVAL(outhdr, SMB2_HDR_PID);
1648 if (flags & SMB2_HDR_FLAG_ASYNC) {
1649 if (search_async_id == async_id) {
1650 found_id = async_id;
1651 break;
1653 } else {
1654 if (search_message_id == message_id) {
1655 found_id = message_id;
1656 break;
1661 if (cur && cur->subreq) {
1662 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1663 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1664 "cancel opcode[%s] mid %llu\n",
1665 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1666 (unsigned long long)found_id ));
1667 tevent_req_cancel(cur->subreq);
1670 return NT_STATUS_OK;
1673 /*************************************************************
1674 Ensure an incoming tid is a valid one for us to access.
1675 Change to the associated uid credentials and chdir to the
1676 valid tid directory.
1677 *************************************************************/
1679 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1681 const uint8_t *inhdr;
1682 uint32_t in_flags;
1683 uint32_t in_tid;
1684 struct smbXsrv_tcon *tcon;
1685 NTSTATUS status;
1686 NTTIME now = timeval_to_nttime(&req->request_time);
1688 req->tcon = NULL;
1690 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1692 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1693 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1695 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1696 in_tid = req->last_tid;
1699 req->last_tid = 0;
1701 status = smb2srv_tcon_lookup(req->session,
1702 in_tid, now, &tcon);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 return status;
1707 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1708 return NT_STATUS_ACCESS_DENIED;
1711 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1712 if (!set_current_service(tcon->compat, 0, true)) {
1713 return NT_STATUS_ACCESS_DENIED;
1716 req->tcon = tcon;
1717 req->last_tid = in_tid;
1719 return NT_STATUS_OK;
1722 /*************************************************************
1723 Ensure an incoming session_id is a valid one for us to access.
1724 *************************************************************/
1726 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1728 const uint8_t *inhdr;
1729 uint32_t in_flags;
1730 uint16_t in_opcode;
1731 uint64_t in_session_id;
1732 struct smbXsrv_session *session = NULL;
1733 struct auth_session_info *session_info;
1734 NTSTATUS status;
1735 NTTIME now = timeval_to_nttime(&req->request_time);
1737 req->session = NULL;
1738 req->tcon = NULL;
1740 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1742 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1743 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1744 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1746 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1747 in_session_id = req->last_session_id;
1750 req->last_session_id = 0;
1752 /* lookup an existing session */
1753 status = smb2srv_session_lookup(req->sconn->conn,
1754 in_session_id, now,
1755 &session);
1756 if (session) {
1757 req->session = session;
1758 req->last_session_id = in_session_id;
1760 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1761 switch (in_opcode) {
1762 case SMB2_OP_SESSSETUP:
1763 status = NT_STATUS_OK;
1764 break;
1765 default:
1766 break;
1769 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1770 switch (in_opcode) {
1771 case SMB2_OP_TCON:
1772 case SMB2_OP_CREATE:
1773 case SMB2_OP_GETINFO:
1774 case SMB2_OP_SETINFO:
1775 return NT_STATUS_INVALID_HANDLE;
1776 default:
1778 * Notice the check for
1779 * (session_info == NULL)
1780 * below.
1782 status = NT_STATUS_OK;
1783 break;
1786 if (!NT_STATUS_IS_OK(status)) {
1787 return status;
1790 session_info = session->global->auth_session_info;
1791 if (session_info == NULL) {
1792 return NT_STATUS_INVALID_HANDLE;
1795 if (in_session_id != req->sconn->conn->last_session_id) {
1796 req->sconn->conn->last_session_id = in_session_id;
1797 set_current_user_info(session_info->unix_info->sanitized_username,
1798 session_info->unix_info->unix_name,
1799 session_info->info->domain_name);
1802 return NT_STATUS_OK;
1805 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1806 uint32_t data_length)
1808 uint16_t needed_charge;
1809 uint16_t credit_charge = 1;
1810 const uint8_t *inhdr;
1812 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1814 if (req->sconn->smb2.supports_multicredit) {
1815 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1816 credit_charge = MAX(credit_charge, 1);
1819 needed_charge = (data_length - 1)/ 65536 + 1;
1821 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1822 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1823 credit_charge, needed_charge));
1825 if (needed_charge > credit_charge) {
1826 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1827 credit_charge, needed_charge));
1828 return NT_STATUS_INVALID_PARAMETER;
1831 return NT_STATUS_OK;
1834 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1835 size_t expected_body_size)
1837 struct iovec *inhdr_v;
1838 const uint8_t *inhdr;
1839 uint16_t opcode;
1840 const uint8_t *inbody;
1841 size_t body_size;
1842 size_t min_dyn_size = expected_body_size & 0x00000001;
1843 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1846 * The following should be checked already.
1848 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1849 return NT_STATUS_INTERNAL_ERROR;
1851 if (req->current_idx > max_idx) {
1852 return NT_STATUS_INTERNAL_ERROR;
1855 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1856 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1857 return NT_STATUS_INTERNAL_ERROR;
1859 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1860 return NT_STATUS_INTERNAL_ERROR;
1863 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1864 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1866 switch (opcode) {
1867 case SMB2_OP_IOCTL:
1868 case SMB2_OP_GETINFO:
1869 min_dyn_size = 0;
1870 break;
1871 case SMB2_OP_WRITE:
1872 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1873 if (req->smb1req->unread_bytes < min_dyn_size) {
1874 return NT_STATUS_INVALID_PARAMETER;
1877 min_dyn_size = 0;
1879 break;
1883 * Now check the expected body size,
1884 * where the last byte might be in the
1885 * dynamic section..
1887 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1888 return NT_STATUS_INVALID_PARAMETER;
1890 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1891 return NT_STATUS_INVALID_PARAMETER;
1894 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1896 body_size = SVAL(inbody, 0x00);
1897 if (body_size != expected_body_size) {
1898 return NT_STATUS_INVALID_PARAMETER;
1901 return NT_STATUS_OK;
1904 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1906 struct smbXsrv_connection *conn = req->sconn->conn;
1907 const struct smbd_smb2_dispatch_table *call = NULL;
1908 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1909 const uint8_t *inhdr;
1910 uint16_t opcode;
1911 uint32_t flags;
1912 uint64_t mid;
1913 NTSTATUS status;
1914 NTSTATUS session_status;
1915 uint32_t allowed_flags;
1916 NTSTATUS return_value;
1917 struct smbXsrv_session *x = NULL;
1918 bool signing_required = false;
1919 bool encryption_required = false;
1921 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1923 /* TODO: verify more things */
1925 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1926 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1927 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1928 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1929 smb2_opcode_name(opcode),
1930 (unsigned long long)mid));
1932 if (conn->protocol >= PROTOCOL_SMB2_02) {
1934 * once the protocol is negotiated
1935 * SMB2_OP_NEGPROT is not allowed anymore
1937 if (opcode == SMB2_OP_NEGPROT) {
1938 /* drop the connection */
1939 return NT_STATUS_INVALID_PARAMETER;
1941 } else {
1943 * if the protocol is not negotiated yet
1944 * only SMB2_OP_NEGPROT is allowed.
1946 if (opcode != SMB2_OP_NEGPROT) {
1947 /* drop the connection */
1948 return NT_STATUS_INVALID_PARAMETER;
1953 * Check if the client provided a valid session id,
1954 * if so smbd_smb2_request_check_session() calls
1955 * set_current_user_info().
1957 * As some command don't require a valid session id
1958 * we defer the check of the session_status
1960 session_status = smbd_smb2_request_check_session(req);
1961 x = req->session;
1962 if (x != NULL) {
1963 signing_required = x->global->signing_required;
1964 encryption_required = x->global->encryption_required;
1966 if (opcode == SMB2_OP_SESSSETUP &&
1967 x->global->channels[0].signing_key.length) {
1968 signing_required = true;
1972 req->do_signing = false;
1973 req->do_encryption = false;
1974 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1975 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1976 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1978 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1979 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1980 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1981 (unsigned long long)x->global->session_wire_id,
1982 (unsigned long long)tf_session_id));
1984 * TODO: windows allows this...
1985 * should we drop the connection?
1987 * For now we just return ACCESS_DENIED
1988 * (Windows clients never trigger this)
1989 * and wait for an update of [MS-SMB2].
1991 return smbd_smb2_request_error(req,
1992 NT_STATUS_ACCESS_DENIED);
1995 req->do_encryption = true;
1998 if (encryption_required && !req->do_encryption) {
1999 return smbd_smb2_request_error(req,
2000 NT_STATUS_ACCESS_DENIED);
2003 call = smbd_smb2_call(opcode);
2004 if (call == NULL) {
2005 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2008 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2009 SMB2_HDR_FLAG_SIGNED |
2010 SMB2_HDR_FLAG_DFS;
2011 if (opcode == SMB2_OP_CANCEL) {
2012 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2014 if ((flags & ~allowed_flags) != 0) {
2015 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2018 if (flags & SMB2_HDR_FLAG_CHAINED) {
2020 * This check is mostly for giving the correct error code
2021 * for compounded requests.
2023 if (!NT_STATUS_IS_OK(session_status)) {
2024 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2026 } else {
2027 req->compat_chain_fsp = NULL;
2030 if (req->do_encryption) {
2031 signing_required = false;
2032 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2033 DATA_BLOB signing_key;
2035 if (x == NULL) {
2037 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2038 * If the SMB2 header of the SMB2 NEGOTIATE
2039 * request has the SMB2_FLAGS_SIGNED bit set in the
2040 * Flags field, the server MUST fail the request
2041 * with STATUS_INVALID_PARAMETER.
2043 * Microsoft test tool checks this.
2046 if ((opcode == SMB2_OP_NEGPROT) &&
2047 (flags & SMB2_HDR_FLAG_SIGNED)) {
2048 status = NT_STATUS_INVALID_PARAMETER;
2049 } else {
2050 status = NT_STATUS_USER_SESSION_DELETED;
2052 return smbd_smb2_request_error(req, status);
2055 signing_key = x->global->channels[0].signing_key;
2058 * If we have a signing key, we should
2059 * sign the response
2061 if (signing_key.length > 0) {
2062 req->do_signing = true;
2065 status = smb2_signing_check_pdu(signing_key,
2066 conn->protocol,
2067 SMBD_SMB2_IN_HDR_IOV(req),
2068 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 return smbd_smb2_request_error(req, status);
2074 * Now that we know the request was correctly signed
2075 * we have to sign the response too.
2077 req->do_signing = true;
2079 if (!NT_STATUS_IS_OK(session_status)) {
2080 return smbd_smb2_request_error(req, session_status);
2082 } else if (opcode == SMB2_OP_CANCEL) {
2083 /* Cancel requests are allowed to skip the signing */
2084 } else if (signing_required) {
2086 * If signing is required we try to sign
2087 * a possible error response
2089 req->do_signing = true;
2090 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2093 if (flags & SMB2_HDR_FLAG_CHAINED) {
2094 req->compound_related = true;
2097 if (call->need_session) {
2098 if (!NT_STATUS_IS_OK(session_status)) {
2099 return smbd_smb2_request_error(req, session_status);
2103 if (call->need_tcon) {
2104 SMB_ASSERT(call->need_session);
2107 * This call needs to be run as user.
2109 * smbd_smb2_request_check_tcon()
2110 * calls change_to_user() on success.
2112 status = smbd_smb2_request_check_tcon(req);
2113 if (!NT_STATUS_IS_OK(status)) {
2114 return smbd_smb2_request_error(req, status);
2116 if (req->tcon->global->encryption_required) {
2117 encryption_required = true;
2119 if (encryption_required && !req->do_encryption) {
2120 return smbd_smb2_request_error(req,
2121 NT_STATUS_ACCESS_DENIED);
2125 if (call->fileid_ofs != 0) {
2126 size_t needed = call->fileid_ofs + 16;
2127 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2128 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2129 uint64_t file_id_persistent;
2130 uint64_t file_id_volatile;
2131 struct files_struct *fsp;
2133 SMB_ASSERT(call->need_tcon);
2135 if (needed > body_size) {
2136 return smbd_smb2_request_error(req,
2137 NT_STATUS_INVALID_PARAMETER);
2140 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2141 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2143 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2144 if (fsp == NULL) {
2145 if (!call->allow_invalid_fileid) {
2146 return smbd_smb2_request_error(req,
2147 NT_STATUS_FILE_CLOSED);
2150 if (file_id_persistent != UINT64_MAX) {
2151 return smbd_smb2_request_error(req,
2152 NT_STATUS_FILE_CLOSED);
2154 if (file_id_volatile != UINT64_MAX) {
2155 return smbd_smb2_request_error(req,
2156 NT_STATUS_FILE_CLOSED);
2161 if (call->as_root) {
2162 SMB_ASSERT(call->fileid_ofs == 0);
2163 /* This call needs to be run as root */
2164 change_to_root_user();
2165 } else {
2166 SMB_ASSERT(call->need_tcon);
2169 switch (opcode) {
2170 case SMB2_OP_NEGPROT:
2172 START_PROFILE(smb2_negprot);
2173 return_value = smbd_smb2_request_process_negprot(req);
2174 END_PROFILE(smb2_negprot);
2176 break;
2178 case SMB2_OP_SESSSETUP:
2180 START_PROFILE(smb2_sesssetup);
2181 return_value = smbd_smb2_request_process_sesssetup(req);
2182 END_PROFILE(smb2_sesssetup);
2184 break;
2186 case SMB2_OP_LOGOFF:
2188 START_PROFILE(smb2_logoff);
2189 return_value = smbd_smb2_request_process_logoff(req);
2190 END_PROFILE(smb2_logoff);
2192 break;
2194 case SMB2_OP_TCON:
2196 START_PROFILE(smb2_tcon);
2197 return_value = smbd_smb2_request_process_tcon(req);
2198 END_PROFILE(smb2_tcon);
2200 break;
2202 case SMB2_OP_TDIS:
2204 START_PROFILE(smb2_tdis);
2205 return_value = smbd_smb2_request_process_tdis(req);
2206 END_PROFILE(smb2_tdis);
2208 break;
2210 case SMB2_OP_CREATE:
2212 START_PROFILE(smb2_create);
2213 return_value = smbd_smb2_request_process_create(req);
2214 END_PROFILE(smb2_create);
2216 break;
2218 case SMB2_OP_CLOSE:
2220 START_PROFILE(smb2_close);
2221 return_value = smbd_smb2_request_process_close(req);
2222 END_PROFILE(smb2_close);
2224 break;
2226 case SMB2_OP_FLUSH:
2228 START_PROFILE(smb2_flush);
2229 return_value = smbd_smb2_request_process_flush(req);
2230 END_PROFILE(smb2_flush);
2232 break;
2234 case SMB2_OP_READ:
2236 START_PROFILE(smb2_read);
2237 return_value = smbd_smb2_request_process_read(req);
2238 END_PROFILE(smb2_read);
2240 break;
2242 case SMB2_OP_WRITE:
2244 START_PROFILE(smb2_write);
2245 return_value = smbd_smb2_request_process_write(req);
2246 END_PROFILE(smb2_write);
2248 break;
2250 case SMB2_OP_LOCK:
2252 START_PROFILE(smb2_lock);
2253 return_value = smbd_smb2_request_process_lock(req);
2254 END_PROFILE(smb2_lock);
2256 break;
2258 case SMB2_OP_IOCTL:
2260 START_PROFILE(smb2_ioctl);
2261 return_value = smbd_smb2_request_process_ioctl(req);
2262 END_PROFILE(smb2_ioctl);
2264 break;
2266 case SMB2_OP_CANCEL:
2268 START_PROFILE(smb2_cancel);
2269 return_value = smbd_smb2_request_process_cancel(req);
2270 END_PROFILE(smb2_cancel);
2272 break;
2274 case SMB2_OP_KEEPALIVE:
2276 START_PROFILE(smb2_keepalive);
2277 return_value = smbd_smb2_request_process_keepalive(req);
2278 END_PROFILE(smb2_keepalive);
2280 break;
2282 case SMB2_OP_FIND:
2284 START_PROFILE(smb2_find);
2285 return_value = smbd_smb2_request_process_find(req);
2286 END_PROFILE(smb2_find);
2288 break;
2290 case SMB2_OP_NOTIFY:
2292 START_PROFILE(smb2_notify);
2293 return_value = smbd_smb2_request_process_notify(req);
2294 END_PROFILE(smb2_notify);
2296 break;
2298 case SMB2_OP_GETINFO:
2300 START_PROFILE(smb2_getinfo);
2301 return_value = smbd_smb2_request_process_getinfo(req);
2302 END_PROFILE(smb2_getinfo);
2304 break;
2306 case SMB2_OP_SETINFO:
2308 START_PROFILE(smb2_setinfo);
2309 return_value = smbd_smb2_request_process_setinfo(req);
2310 END_PROFILE(smb2_setinfo);
2312 break;
2314 case SMB2_OP_BREAK:
2316 START_PROFILE(smb2_break);
2317 return_value = smbd_smb2_request_process_break(req);
2318 END_PROFILE(smb2_break);
2320 break;
2322 default:
2323 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2324 break;
2326 return return_value;
2329 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2331 struct smbd_server_connection *sconn = req->sconn;
2332 struct smbXsrv_connection *conn = req->sconn->conn;
2333 int first_idx = 1;
2334 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2335 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2336 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2337 NTSTATUS status;
2339 req->subreq = NULL;
2340 TALLOC_FREE(req->async_te);
2342 if (req->do_encryption &&
2343 (firsttf->iov_len == 0) &&
2344 (req->first_key.length == 0) &&
2345 (req->session != NULL) &&
2346 (req->session->global->encryption_key.length != 0))
2348 DATA_BLOB encryption_key = req->session->global->encryption_key;
2349 uint8_t *tf;
2350 uint64_t session_id = req->session->global->session_wire_id;
2351 struct smbXsrv_session *x = req->session;
2352 uint64_t nonce_high;
2353 uint64_t nonce_low;
2355 nonce_high = x->nonce_high;
2356 nonce_low = x->nonce_low;
2358 x->nonce_low += 1;
2359 if (x->nonce_low == 0) {
2360 x->nonce_low += 1;
2361 x->nonce_high += 1;
2365 * We need to place the SMB2_TRANSFORM header before the
2366 * first SMB2 header
2370 * we need to remember the encryption key
2371 * and defer the signing/encryption until
2372 * we are sure that we do not change
2373 * the header again.
2375 req->first_key = data_blob_dup_talloc(req, encryption_key);
2376 if (req->first_key.data == NULL) {
2377 return NT_STATUS_NO_MEMORY;
2380 tf = talloc_zero_array(req, uint8_t,
2381 SMB2_TF_HDR_SIZE);
2382 if (tf == NULL) {
2383 return NT_STATUS_NO_MEMORY;
2386 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2387 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2388 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2389 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2391 firsttf->iov_base = (void *)tf;
2392 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2395 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2396 (req->last_key.length > 0) &&
2397 (firsttf->iov_len == 0))
2399 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2400 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2403 * As we are sure the header of the last request in the
2404 * compound chain will not change, we can to sign here
2405 * with the last signing key we remembered.
2407 status = smb2_signing_sign_pdu(req->last_key,
2408 conn->protocol,
2409 lasthdr,
2410 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2411 if (!NT_STATUS_IS_OK(status)) {
2412 return status;
2415 if (req->last_key.length > 0) {
2416 data_blob_clear_free(&req->last_key);
2419 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2421 if (req->current_idx < req->out.vector_count) {
2423 * We must process the remaining compound
2424 * SMB2 requests before any new incoming SMB2
2425 * requests. This is because incoming SMB2
2426 * requests may include a cancel for a
2427 * compound request we haven't processed
2428 * yet.
2430 struct tevent_immediate *im = tevent_create_immediate(req);
2431 if (!im) {
2432 return NT_STATUS_NO_MEMORY;
2435 if (req->do_signing && firsttf->iov_len == 0) {
2436 struct smbXsrv_session *x = req->session;
2437 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2440 * we need to remember the signing key
2441 * and defer the signing until
2442 * we are sure that we do not change
2443 * the header again.
2445 req->last_key = data_blob_dup_talloc(req, signing_key);
2446 if (req->last_key.data == NULL) {
2447 return NT_STATUS_NO_MEMORY;
2451 tevent_schedule_immediate(im,
2452 req->sconn->ev_ctx,
2453 smbd_smb2_request_dispatch_immediate,
2454 req);
2455 return NT_STATUS_OK;
2458 if (req->compound_related) {
2459 req->compound_related = false;
2462 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2464 /* Set credit for these operations (zero credits if this
2465 is a final reply for an async operation). */
2466 smb2_calculate_credits(req, req);
2469 * now check if we need to sign the current response
2471 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2472 status = smb2_signing_encrypt_pdu(req->first_key,
2473 conn->protocol,
2474 firsttf,
2475 req->out.vector_count - first_idx);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 return status;
2479 } else if (req->do_signing) {
2480 struct smbXsrv_session *x = req->session;
2481 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2483 status = smb2_signing_sign_pdu(signing_key,
2484 conn->protocol,
2485 outhdr,
2486 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2487 if (!NT_STATUS_IS_OK(status)) {
2488 return status;
2491 if (req->first_key.length > 0) {
2492 data_blob_clear_free(&req->first_key);
2495 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2496 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2497 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2498 /* Dynamic part is NULL. Chop it off,
2499 We're going to send it via sendfile. */
2500 req->out.vector_count -= 1;
2504 * We're done with this request -
2505 * move it off the "being processed" queue.
2507 DLIST_REMOVE(req->sconn->smb2.requests, req);
2509 req->queue_entry.mem_ctx = req;
2510 req->queue_entry.vector = req->out.vector;
2511 req->queue_entry.count = req->out.vector_count;
2512 DLIST_ADD_END(conn->smb2.send_queue, &req->queue_entry, NULL);
2513 conn->smb2.send_queue_len++;
2515 status = smbd_smb2_flush_send_queue(sconn);
2516 if (!NT_STATUS_IS_OK(status)) {
2517 return status;
2520 return NT_STATUS_OK;
2523 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2525 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2526 struct tevent_immediate *im,
2527 void *private_data)
2529 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2530 struct smbd_smb2_request);
2531 struct smbd_server_connection *sconn = req->sconn;
2532 NTSTATUS status;
2534 TALLOC_FREE(im);
2536 if (DEBUGLEVEL >= 10) {
2537 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2538 req->current_idx, req->in.vector_count));
2539 print_req_vectors(req);
2542 status = smbd_smb2_request_dispatch(req);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 smbd_server_connection_terminate(sconn, nt_errstr(status));
2545 return;
2548 status = smbd_smb2_request_next_incoming(sconn);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 smbd_server_connection_terminate(sconn, nt_errstr(status));
2551 return;
2555 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2556 NTSTATUS status,
2557 DATA_BLOB body, DATA_BLOB *dyn,
2558 const char *location)
2560 uint8_t *outhdr;
2561 struct iovec *outbody_v;
2562 struct iovec *outdyn_v;
2563 uint32_t next_command_ofs;
2565 DEBUG(10,("smbd_smb2_request_done_ex: "
2566 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2567 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2568 dyn ? "yes": "no",
2569 (unsigned int)(dyn ? dyn->length : 0),
2570 location));
2572 if (body.length < 2) {
2573 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2576 if ((body.length % 2) != 0) {
2577 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2580 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2581 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2582 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2584 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2585 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2587 outbody_v->iov_base = (void *)body.data;
2588 outbody_v->iov_len = body.length;
2590 if (dyn) {
2591 outdyn_v->iov_base = (void *)dyn->data;
2592 outdyn_v->iov_len = dyn->length;
2593 } else {
2594 outdyn_v->iov_base = NULL;
2595 outdyn_v->iov_len = 0;
2598 /* see if we need to recalculate the offset to the next response */
2599 if (next_command_ofs > 0) {
2600 next_command_ofs = SMB2_HDR_BODY;
2601 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2602 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2605 if ((next_command_ofs % 8) != 0) {
2606 size_t pad_size = 8 - (next_command_ofs % 8);
2607 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2609 * if the dyn buffer is empty
2610 * we can use it to add padding
2612 uint8_t *pad;
2614 pad = talloc_zero_array(req,
2615 uint8_t, pad_size);
2616 if (pad == NULL) {
2617 return smbd_smb2_request_error(req,
2618 NT_STATUS_NO_MEMORY);
2621 outdyn_v->iov_base = (void *)pad;
2622 outdyn_v->iov_len = pad_size;
2623 } else {
2625 * For now we copy the dynamic buffer
2626 * and add the padding to the new buffer
2628 size_t old_size;
2629 uint8_t *old_dyn;
2630 size_t new_size;
2631 uint8_t *new_dyn;
2633 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2634 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2636 new_size = old_size + pad_size;
2637 new_dyn = talloc_zero_array(req,
2638 uint8_t, new_size);
2639 if (new_dyn == NULL) {
2640 return smbd_smb2_request_error(req,
2641 NT_STATUS_NO_MEMORY);
2644 memcpy(new_dyn, old_dyn, old_size);
2645 memset(new_dyn + old_size, 0, pad_size);
2647 outdyn_v->iov_base = (void *)new_dyn;
2648 outdyn_v->iov_len = new_size;
2650 next_command_ofs += pad_size;
2653 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2655 return smbd_smb2_request_reply(req);
2658 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2659 NTSTATUS status,
2660 DATA_BLOB *info,
2661 const char *location)
2663 struct smbXsrv_connection *xconn = req->sconn->conn;
2664 DATA_BLOB body;
2665 DATA_BLOB _dyn;
2666 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2667 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2669 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2670 req->current_idx, nt_errstr(status), info ? " +info" : "",
2671 location));
2673 if (unread_bytes) {
2674 /* Recvfile error. Drain incoming socket. */
2675 size_t ret;
2677 errno = 0;
2678 ret = drain_socket(xconn->transport.sock, unread_bytes);
2679 if (ret != unread_bytes) {
2680 NTSTATUS error;
2682 if (errno == 0) {
2683 error = NT_STATUS_IO_DEVICE_ERROR;
2684 } else {
2685 error = map_nt_error_from_unix_common(errno);
2688 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2689 "ret[%u] errno[%d] => %s\n",
2690 (unsigned)unread_bytes,
2691 (unsigned)ret, errno, nt_errstr(error)));
2692 return error;
2696 body.data = outhdr + SMB2_HDR_BODY;
2697 body.length = 8;
2698 SSVAL(body.data, 0, 9);
2700 if (info) {
2701 SIVAL(body.data, 0x04, info->length);
2702 } else {
2703 /* Allocated size of req->out.vector[i].iov_base
2704 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2705 * 1 byte without having to do an alloc.
2707 info = &_dyn;
2708 info->data = ((uint8_t *)outhdr) +
2709 OUTVEC_ALLOC_SIZE - 1;
2710 info->length = 1;
2711 SCVAL(info->data, 0, 0);
2715 * Note: Even if there is an error, continue to process the request.
2716 * per MS-SMB2.
2719 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2723 struct smbd_smb2_send_break_state {
2724 struct smbd_server_connection *sconn;
2725 struct smbd_smb2_send_queue queue_entry;
2726 uint8_t nbt_hdr[NBT_HDR_SIZE];
2727 uint8_t tf[SMB2_TF_HDR_SIZE];
2728 uint8_t hdr[SMB2_HDR_BODY];
2729 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2730 uint8_t body[1];
2733 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2734 struct smbXsrv_session *session,
2735 struct smbXsrv_tcon *tcon,
2736 const uint8_t *body,
2737 size_t body_len)
2739 struct smbd_smb2_send_break_state *state;
2740 struct smbXsrv_connection *conn = sconn->conn;
2741 bool do_encryption = session->global->encryption_required;
2742 uint64_t nonce_high = 0;
2743 uint64_t nonce_low = 0;
2744 NTSTATUS status;
2745 size_t statelen;
2747 if (tcon->global->encryption_required) {
2748 do_encryption = true;
2751 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2752 body_len;
2754 state = talloc_zero_size(sconn, statelen);
2755 if (state == NULL) {
2756 return NT_STATUS_NO_MEMORY;
2758 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2759 state->sconn = sconn;
2761 if (do_encryption) {
2762 nonce_high = session->nonce_high;
2763 nonce_low = session->nonce_low;
2765 session->nonce_low += 1;
2766 if (session->nonce_low == 0) {
2767 session->nonce_low += 1;
2768 session->nonce_high += 1;
2772 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2773 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2774 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2775 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2777 SIVAL(state->hdr, 0, SMB2_MAGIC);
2778 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2779 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2780 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2781 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2782 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2783 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2784 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2785 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2786 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2787 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2788 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2789 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2791 state->vector[0] = (struct iovec) {
2792 .iov_base = state->nbt_hdr,
2793 .iov_len = sizeof(state->nbt_hdr)
2796 if (do_encryption) {
2797 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2798 .iov_base = state->tf,
2799 .iov_len = sizeof(state->tf)
2801 } else {
2802 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2803 .iov_base = NULL,
2804 .iov_len = 0
2808 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2809 .iov_base = state->hdr,
2810 .iov_len = sizeof(state->hdr)
2813 memcpy(state->body, body, body_len);
2815 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2816 .iov_base = state->body,
2817 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2821 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2824 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2826 if (do_encryption) {
2827 DATA_BLOB encryption_key = session->global->encryption_key;
2829 status = smb2_signing_encrypt_pdu(encryption_key,
2830 conn->protocol,
2831 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2832 SMBD_SMB2_NUM_IOV_PER_REQ);
2833 if (!NT_STATUS_IS_OK(status)) {
2834 return status;
2838 state->queue_entry.mem_ctx = state;
2839 state->queue_entry.vector = state->vector;
2840 state->queue_entry.count = ARRAY_SIZE(state->vector);
2841 DLIST_ADD_END(conn->smb2.send_queue, &state->queue_entry, NULL);
2842 conn->smb2.send_queue_len++;
2844 status = smbd_smb2_flush_send_queue(sconn);
2845 if (!NT_STATUS_IS_OK(status)) {
2846 return status;
2849 return NT_STATUS_OK;
2852 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2853 struct smbXsrv_session *session,
2854 struct smbXsrv_tcon *tcon,
2855 struct smbXsrv_open *op,
2856 uint8_t oplock_level)
2858 uint8_t body[0x18];
2860 SSVAL(body, 0x00, sizeof(body));
2861 SCVAL(body, 0x02, oplock_level);
2862 SCVAL(body, 0x03, 0); /* reserved */
2863 SIVAL(body, 0x04, 0); /* reserved */
2864 SBVAL(body, 0x08, op->global->open_persistent_id);
2865 SBVAL(body, 0x10, op->global->open_volatile_id);
2867 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2870 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2872 NTSTATUS status;
2873 uint32_t flags;
2874 uint64_t file_id_persistent;
2875 uint64_t file_id_volatile;
2876 struct smbXsrv_open *op = NULL;
2877 struct files_struct *fsp = NULL;
2878 const uint8_t *body = NULL;
2881 * This is only called with a pktbuf
2882 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2883 * bytes
2886 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2887 /* Transform header. Cannot recvfile. */
2888 return false;
2890 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2891 /* Not SMB2. Normal error path will cope. */
2892 return false;
2894 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2895 /* Not SMB2. Normal error path will cope. */
2896 return false;
2898 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2899 /* Needs to be a WRITE. */
2900 return false;
2902 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2903 /* Chained. Cannot recvfile. */
2904 return false;
2906 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2907 if (flags & SMB2_HDR_FLAG_CHAINED) {
2908 /* Chained. Cannot recvfile. */
2909 return false;
2911 if (flags & SMB2_HDR_FLAG_SIGNED) {
2912 /* Signed. Cannot recvfile. */
2913 return false;
2916 body = &state->pktbuf[SMB2_HDR_BODY];
2918 file_id_persistent = BVAL(body, 0x10);
2919 file_id_volatile = BVAL(body, 0x18);
2921 status = smb2srv_open_lookup(state->req->sconn->conn,
2922 file_id_persistent,
2923 file_id_volatile,
2924 0, /* now */
2925 &op);
2926 if (!NT_STATUS_IS_OK(status)) {
2927 return false;
2930 fsp = op->compat;
2931 if (fsp == NULL) {
2932 return false;
2934 if (fsp->conn == NULL) {
2935 return false;
2938 if (IS_IPC(fsp->conn)) {
2939 return false;
2941 if (IS_PRINT(fsp->conn)) {
2942 return false;
2945 DEBUG(10,("Doing recvfile write len = %u\n",
2946 (unsigned int)(state->pktfull - state->pktlen)));
2948 return true;
2951 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2953 struct smbXsrv_connection *xconn = sconn->conn;
2954 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2955 size_t max_send_queue_len;
2956 size_t cur_send_queue_len;
2958 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2960 * we're not supposed to do any io
2962 return NT_STATUS_OK;
2965 if (state->req != NULL) {
2967 * if there is already a tstream_readv_pdu
2968 * pending, we are done.
2970 return NT_STATUS_OK;
2973 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2974 cur_send_queue_len = xconn->smb2.send_queue_len;
2976 if (cur_send_queue_len > max_send_queue_len) {
2978 * if we have a lot of requests to send,
2979 * we wait until they are on the wire until we
2980 * ask for the next request.
2982 return NT_STATUS_OK;
2985 /* ask for the next request */
2986 ZERO_STRUCTP(state);
2987 state->req = smbd_smb2_request_allocate(sconn);
2988 if (state->req == NULL) {
2989 return NT_STATUS_NO_MEMORY;
2991 state->req->sconn = sconn;
2992 state->min_recv_size = lp_min_receive_file_size();
2994 TEVENT_FD_READABLE(xconn->transport.fde);
2996 return NT_STATUS_OK;
2999 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3000 uint8_t *inbuf, size_t size)
3002 NTSTATUS status;
3003 struct smbd_smb2_request *req = NULL;
3005 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3006 (unsigned int)size));
3008 status = smbd_initialize_smb2(sconn);
3009 if (!NT_STATUS_IS_OK(status)) {
3010 smbd_server_connection_terminate(sconn, nt_errstr(status));
3011 return;
3014 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3015 if (!NT_STATUS_IS_OK(status)) {
3016 smbd_server_connection_terminate(sconn, nt_errstr(status));
3017 return;
3020 status = smbd_smb2_request_validate(req);
3021 if (!NT_STATUS_IS_OK(status)) {
3022 smbd_server_connection_terminate(sconn, nt_errstr(status));
3023 return;
3026 status = smbd_smb2_request_setup_out(req);
3027 if (!NT_STATUS_IS_OK(status)) {
3028 smbd_server_connection_terminate(sconn, nt_errstr(status));
3029 return;
3032 status = smbd_smb2_request_dispatch(req);
3033 if (!NT_STATUS_IS_OK(status)) {
3034 smbd_server_connection_terminate(sconn, nt_errstr(status));
3035 return;
3038 status = smbd_smb2_request_next_incoming(sconn);
3039 if (!NT_STATUS_IS_OK(status)) {
3040 smbd_server_connection_terminate(sconn, nt_errstr(status));
3041 return;
3044 sconn->num_requests++;
3047 static int socket_error_from_errno(int ret,
3048 int sys_errno,
3049 bool *retry)
3051 *retry = false;
3053 if (ret >= 0) {
3054 return 0;
3057 if (ret != -1) {
3058 return EIO;
3061 if (sys_errno == 0) {
3062 return EIO;
3065 if (sys_errno == EINTR) {
3066 *retry = true;
3067 return sys_errno;
3070 if (sys_errno == EINPROGRESS) {
3071 *retry = true;
3072 return sys_errno;
3075 if (sys_errno == EAGAIN) {
3076 *retry = true;
3077 return sys_errno;
3080 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3081 if (sys_errno == ENOMEM) {
3082 *retry = true;
3083 return sys_errno;
3086 #ifdef EWOULDBLOCK
3087 #if EWOULDBLOCK != EAGAIN
3088 if (sys_errno == EWOULDBLOCK) {
3089 *retry = true;
3090 return sys_errno;
3092 #endif
3093 #endif
3095 return sys_errno;
3098 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3100 struct smbXsrv_connection *xconn = sconn->conn;
3101 int ret;
3102 int err;
3103 bool retry;
3105 if (xconn->smb2.send_queue == NULL) {
3106 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3107 return NT_STATUS_OK;
3110 while (xconn->smb2.send_queue != NULL) {
3111 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3113 if (e->sendfile_header != NULL) {
3114 size_t size = 0;
3115 size_t i = 0;
3116 uint8_t *buf;
3118 for (i=0; i < e->count; i++) {
3119 size += e->vector[i].iov_len;
3122 if (size <= e->sendfile_header->length) {
3123 buf = e->sendfile_header->data;
3124 } else {
3125 buf = talloc_array(e->mem_ctx, uint8_t, size);
3126 if (buf == NULL) {
3127 return NT_STATUS_NO_MEMORY;
3131 size = 0;
3132 for (i=0; i < e->count; i++) {
3133 memcpy(buf+size,
3134 e->vector[i].iov_base,
3135 e->vector[i].iov_len);
3136 size += e->vector[i].iov_len;
3139 e->sendfile_header->data = buf;
3140 e->sendfile_header->length = size;
3141 e->count = 0;
3143 xconn->smb2.send_queue_len--;
3144 DLIST_REMOVE(xconn->smb2.send_queue, e);
3146 * This triggers the sendfile path via
3147 * the destructor.
3149 talloc_free(e->mem_ctx);
3150 continue;
3153 ret = writev(xconn->transport.sock, e->vector, e->count);
3154 if (ret == 0) {
3155 /* propagate end of file */
3156 return NT_STATUS_INTERNAL_ERROR;
3158 err = socket_error_from_errno(ret, errno, &retry);
3159 if (retry) {
3160 /* retry later */
3161 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3162 return NT_STATUS_OK;
3164 if (err != 0) {
3165 return map_nt_error_from_unix_common(err);
3167 while (ret > 0) {
3168 if (ret < e->vector[0].iov_len) {
3169 uint8_t *base;
3170 base = (uint8_t *)e->vector[0].iov_base;
3171 base += ret;
3172 e->vector[0].iov_base = (void *)base;
3173 e->vector[0].iov_len -= ret;
3174 break;
3176 ret -= e->vector[0].iov_len;
3177 e->vector += 1;
3178 e->count -= 1;
3182 * there're maybe some empty vectors at the end
3183 * which we need to skip, otherwise we would get
3184 * ret == 0 from the readv() call and return EPIPE
3186 while (e->count > 0) {
3187 if (e->vector[0].iov_len > 0) {
3188 break;
3190 e->vector += 1;
3191 e->count -= 1;
3194 if (e->count > 0) {
3195 /* we have more to write */
3196 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3197 return NT_STATUS_OK;
3200 xconn->smb2.send_queue_len--;
3201 DLIST_REMOVE(xconn->smb2.send_queue, e);
3202 talloc_free(e->mem_ctx);
3205 return NT_STATUS_OK;
3208 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3209 uint16_t fde_flags)
3211 struct smbXsrv_connection *xconn = sconn->conn;
3212 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3213 struct smbd_smb2_request *req = NULL;
3214 size_t min_recvfile_size = UINT32_MAX;
3215 int ret;
3216 int err;
3217 bool retry;
3218 NTSTATUS status;
3219 NTTIME now;
3221 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3223 * we're not supposed to do any io
3225 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3226 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3227 return NT_STATUS_OK;
3230 if (fde_flags & TEVENT_FD_WRITE) {
3231 status = smbd_smb2_flush_send_queue(sconn);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 return status;
3237 if (!(fde_flags & TEVENT_FD_READ)) {
3238 return NT_STATUS_OK;
3241 if (state->req == NULL) {
3242 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3243 return NT_STATUS_OK;
3246 again:
3247 if (!state->hdr.done) {
3248 state->hdr.done = true;
3250 state->vector.iov_base = (void *)state->hdr.nbt;
3251 state->vector.iov_len = NBT_HDR_SIZE;
3254 ret = readv(xconn->transport.sock, &state->vector, 1);
3255 if (ret == 0) {
3256 /* propagate end of file */
3257 return NT_STATUS_END_OF_FILE;
3259 err = socket_error_from_errno(ret, errno, &retry);
3260 if (retry) {
3261 /* retry later */
3262 TEVENT_FD_READABLE(xconn->transport.fde);
3263 return NT_STATUS_OK;
3265 if (err != 0) {
3266 return map_nt_error_from_unix_common(err);
3269 if (ret < state->vector.iov_len) {
3270 uint8_t *base;
3271 base = (uint8_t *)state->vector.iov_base;
3272 base += ret;
3273 state->vector.iov_base = (void *)base;
3274 state->vector.iov_len -= ret;
3275 /* we have more to read */
3276 TEVENT_FD_READABLE(xconn->transport.fde);
3277 return NT_STATUS_OK;
3280 if (state->pktlen > 0) {
3281 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3283 * Not a possible receivefile write.
3284 * Read the rest of the data.
3286 state->doing_receivefile = false;
3288 state->pktbuf = talloc_realloc(state->req,
3289 state->pktbuf,
3290 uint8_t,
3291 state->pktfull);
3292 if (state->pktbuf == NULL) {
3293 return NT_STATUS_NO_MEMORY;
3296 state->vector.iov_base = (void *)(state->pktbuf +
3297 state->pktlen);
3298 state->vector.iov_len = (state->pktfull -
3299 state->pktlen);
3301 state->pktlen = state->pktfull;
3302 goto again;
3306 * Either this is a receivefile write so we've
3307 * done a short read, or if not we have all the data.
3309 goto got_full;
3313 * Now we analyze the NBT header
3315 if (state->hdr.nbt[0] != 0x00) {
3316 state->min_recv_size = 0;
3318 state->pktfull = smb2_len(state->hdr.nbt);
3319 if (state->pktfull == 0) {
3320 goto got_full;
3323 if (state->min_recv_size != 0) {
3324 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3325 min_recvfile_size += state->min_recv_size;
3328 if (state->pktfull > min_recvfile_size) {
3330 * Might be a receivefile write. Read the SMB2 HEADER +
3331 * SMB2_WRITE header first. Set 'doing_receivefile'
3332 * as we're *attempting* receivefile write. If this
3333 * turns out not to be a SMB2_WRITE request or otherwise
3334 * not suitable then we'll just read the rest of the data
3335 * the next time this function is called.
3337 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3338 state->doing_receivefile = true;
3339 } else {
3340 state->pktlen = state->pktfull;
3343 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3344 if (state->pktbuf == NULL) {
3345 return NT_STATUS_NO_MEMORY;
3348 state->vector.iov_base = (void *)state->pktbuf;
3349 state->vector.iov_len = state->pktlen;
3351 goto again;
3353 got_full:
3355 if (state->hdr.nbt[0] != 0x00) {
3356 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3357 state->hdr.nbt[0]));
3359 req = state->req;
3360 ZERO_STRUCTP(state);
3361 state->req = req;
3362 state->min_recv_size = lp_min_receive_file_size();
3363 req = NULL;
3364 goto again;
3367 req = state->req;
3368 state->req = NULL;
3370 req->request_time = timeval_current();
3371 now = timeval_to_nttime(&req->request_time);
3373 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3374 now,
3375 state->pktbuf,
3376 state->pktlen,
3377 req,
3378 &req->in.vector,
3379 &req->in.vector_count);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 return status;
3384 if (state->doing_receivefile) {
3385 req->smb1req = talloc_zero(req, struct smb_request);
3386 if (req->smb1req == NULL) {
3387 return NT_STATUS_NO_MEMORY;
3389 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3392 ZERO_STRUCTP(state);
3394 req->current_idx = 1;
3396 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3397 req->current_idx, req->in.vector_count));
3399 status = smbd_smb2_request_validate(req);
3400 if (!NT_STATUS_IS_OK(status)) {
3401 return status;
3404 status = smbd_smb2_request_setup_out(req);
3405 if (!NT_STATUS_IS_OK(status)) {
3406 return status;
3409 status = smbd_smb2_request_dispatch(req);
3410 if (!NT_STATUS_IS_OK(status)) {
3411 return status;
3414 sconn->num_requests++;
3416 /* The timeout_processing function isn't run nearly
3417 often enough to implement 'max log size' without
3418 overrunning the size of the file by many megabytes.
3419 This is especially true if we are running at debug
3420 level 10. Checking every 50 SMB2s is a nice
3421 tradeoff of performance vs log file size overrun. */
3423 if ((sconn->num_requests % 50) == 0 &&
3424 need_to_check_log_size()) {
3425 change_to_root_user();
3426 check_log_size();
3429 status = smbd_smb2_request_next_incoming(sconn);
3430 if (!NT_STATUS_IS_OK(status)) {
3431 return status;
3434 return NT_STATUS_OK;
3437 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3438 struct tevent_fd *fde,
3439 uint16_t flags,
3440 void *private_data)
3442 struct smbd_server_connection *sconn =
3443 talloc_get_type_abort(private_data,
3444 struct smbd_server_connection);
3445 NTSTATUS status;
3447 status = smbd_smb2_io_handler(sconn, flags);
3448 if (!NT_STATUS_IS_OK(status)) {
3449 smbd_server_connection_terminate(sconn, nt_errstr(status));
3450 return;