smbd: Make nbt_hdr a field of its own in smbd_smb2_send_oplock_break
[Samba.git] / source3 / smbd / smb2_server.c
blobe3444144f74edcc269442b5fc91088ffe73e1d02
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
35 uint16_t flags,
36 void *private_data);
37 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn);
39 static const struct smbd_smb2_dispatch_table {
40 uint16_t opcode;
41 const char *name;
42 bool need_session;
43 bool need_tcon;
44 bool as_root;
45 uint16_t fileid_ofs;
46 bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
50 _OP(SMB2_OP_NEGPROT),
51 .as_root = true,
52 },{
53 _OP(SMB2_OP_SESSSETUP),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_LOGOFF),
57 .need_session = true,
58 .as_root = true,
59 },{
60 _OP(SMB2_OP_TCON),
61 .need_session = true,
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
69 .as_root = true,
70 },{
71 _OP(SMB2_OP_TDIS),
72 .need_session = true,
73 .need_tcon = true,
74 .as_root = true,
75 },{
76 _OP(SMB2_OP_CREATE),
77 .need_session = true,
78 .need_tcon = true,
79 },{
80 _OP(SMB2_OP_CLOSE),
81 .need_session = true,
82 .need_tcon = true,
83 .fileid_ofs = 0x08,
84 },{
85 _OP(SMB2_OP_FLUSH),
86 .need_session = true,
87 .need_tcon = true,
88 .fileid_ofs = 0x08,
89 },{
90 _OP(SMB2_OP_READ),
91 .need_session = true,
92 .need_tcon = true,
93 .fileid_ofs = 0x10,
94 },{
95 _OP(SMB2_OP_WRITE),
96 .need_session = true,
97 .need_tcon = true,
98 .fileid_ofs = 0x10,
99 },{
100 _OP(SMB2_OP_LOCK),
101 .need_session = true,
102 .need_tcon = true,
103 .fileid_ofs = 0x08,
105 _OP(SMB2_OP_IOCTL),
106 .need_session = true,
107 .need_tcon = true,
108 .fileid_ofs = 0x08,
109 .allow_invalid_fileid = true,
111 _OP(SMB2_OP_CANCEL),
112 .as_root = true,
114 _OP(SMB2_OP_KEEPALIVE),
115 .as_root = true,
117 _OP(SMB2_OP_FIND),
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x08,
122 _OP(SMB2_OP_NOTIFY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_GETINFO),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x18,
132 _OP(SMB2_OP_SETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x10,
137 _OP(SMB2_OP_BREAK),
138 .need_session = true,
139 .need_tcon = true,
141 * we do not set
142 * .fileid_ofs here
143 * as LEASE breaks does not
144 * have a file id
149 const char *smb2_opcode_name(uint16_t opcode)
151 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table[opcode].name;
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 const struct smbd_smb2_dispatch_table *ret = NULL;
161 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
162 return NULL;
165 ret = &smbd_smb2_table[opcode];
167 SMB_ASSERT(ret->opcode == opcode);
169 return ret;
172 static void print_req_vectors(const struct smbd_smb2_request *req)
174 int i;
176 for (i = 0; i < req->in.vector_count; i++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
178 (unsigned int)i,
179 (unsigned int)req->in.vector[i].iov_len);
181 for (i = 0; i < req->out.vector_count; i++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
183 (unsigned int)i,
184 (unsigned int)req->out.vector[i].iov_len);
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 if (size < (4 + SMB2_HDR_BODY)) {
191 return false;
194 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
195 return false;
198 return true;
201 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
203 TALLOC_FREE(sconn->smb1.fde);
205 sconn->smb2.send_queue = NULL;
207 sconn->smb2.seqnum_low = 0;
208 sconn->smb2.seqnum_range = 1;
209 sconn->smb2.credits_granted = 1;
210 sconn->smb2.max_credits = lp_smb2_max_credits();
211 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
212 sconn->smb2.max_credits);
213 if (sconn->smb2.credits_bitmap == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
218 sconn,
219 sconn->sock,
220 TEVENT_FD_READ,
221 smbd_smb2_connection_handler,
222 sconn);
223 if (sconn->smb2.fde == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(sconn->sock, false);
229 return NT_STATUS_OK;
232 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
233 #define _smb2_setlen(_buf,len) do { \
234 uint8_t *buf = (uint8_t *)_buf; \
235 buf[0] = 0; \
236 buf[1] = ((len)&0xFF0000)>>16; \
237 buf[2] = ((len)&0xFF00)>>8; \
238 buf[3] = (len)&0xFF; \
239 } while (0)
241 static void smb2_setup_nbt_length(struct iovec *vector, int count)
243 size_t len = 0;
244 int i;
246 for (i=1; i < count; i++) {
247 len += vector[i].iov_len;
250 _smb2_setlen(vector[0].iov_base, len);
253 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
255 if (req->first_key.length > 0) {
256 data_blob_clear_free(&req->first_key);
258 if (req->last_key.length > 0) {
259 data_blob_clear_free(&req->last_key);
261 return 0;
264 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
266 TALLOC_CTX *mem_pool;
267 struct smbd_smb2_request *req;
269 #if 0
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 #else
273 mem_pool = talloc_tos();
274 #endif
275 if (mem_pool == NULL) {
276 return NULL;
279 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 if (req == NULL) {
281 talloc_free(mem_pool);
282 return NULL;
284 talloc_reparent(mem_pool, mem_ctx, req);
285 #if 0
286 TALLOC_FREE(mem_pool);
287 #endif
289 req->last_session_id = UINT64_MAX;
290 req->last_tid = UINT32_MAX;
292 talloc_set_destructor(req, smbd_smb2_request_destructor);
294 return req;
297 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
298 NTTIME now,
299 uint8_t *buf,
300 size_t buflen,
301 struct smbd_smb2_request *req,
302 struct iovec **piov,
303 int *pnum_iov)
305 TALLOC_CTX *mem_ctx = req;
306 struct iovec *iov;
307 int num_iov = 1;
308 size_t taken = 0;
309 uint8_t *first_hdr = buf;
310 size_t verified_buflen = 0;
311 uint8_t *tf = NULL;
312 size_t tf_len = 0;
315 * Note: index '0' is reserved for the transport protocol
317 iov = req->in._vector;
319 while (taken < buflen) {
320 size_t len = buflen - taken;
321 uint8_t *hdr = first_hdr + taken;
322 struct iovec *cur;
323 size_t full_size;
324 size_t next_command_ofs;
325 uint16_t body_size;
326 uint8_t *body = NULL;
327 uint32_t dyn_size;
328 uint8_t *dyn = NULL;
329 struct iovec *iov_alloc = NULL;
331 if (iov != req->in._vector) {
332 iov_alloc = iov;
335 if (verified_buflen > taken) {
336 len = verified_buflen - taken;
337 } else {
338 tf = NULL;
339 tf_len = 0;
342 if (len < 4) {
343 DEBUG(10, ("%d bytes left, expected at least %d\n",
344 (int)len, 4));
345 goto inval;
347 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
348 struct smbXsrv_session *s = NULL;
349 uint64_t uid;
350 struct iovec tf_iov[2];
351 NTSTATUS status;
352 size_t enc_len;
354 if (conn->protocol < PROTOCOL_SMB2_24) {
355 DEBUG(10, ("Got SMB2_TRANSFORM header, "
356 "but dialect[0x%04X] is used\n",
357 conn->smb2.server.dialect));
358 goto inval;
361 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but not negotiated "
364 "client[0x%08X] server[0x%08X]\n",
365 conn->smb2.client.capabilities,
366 conn->smb2.server.capabilities));
367 goto inval;
370 if (len < SMB2_TF_HDR_SIZE) {
371 DEBUG(1, ("%d bytes left, expected at least %d\n",
372 (int)len, SMB2_TF_HDR_SIZE));
373 goto inval;
375 tf = hdr;
376 tf_len = SMB2_TF_HDR_SIZE;
377 taken += tf_len;
379 hdr = first_hdr + taken;
380 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
381 uid = BVAL(tf, SMB2_TF_SESSION_ID);
383 if (len < SMB2_TF_HDR_SIZE + enc_len) {
384 DEBUG(1, ("%d bytes left, expected at least %d\n",
385 (int)len,
386 (int)(SMB2_TF_HDR_SIZE + enc_len)));
387 goto inval;
390 status = smb2srv_session_lookup(conn, uid, now, &s);
391 if (s == NULL) {
392 DEBUG(1, ("invalid session[%llu] in "
393 "SMB2_TRANSFORM header\n",
394 (unsigned long long)uid));
395 TALLOC_FREE(iov_alloc);
396 return NT_STATUS_USER_SESSION_DELETED;
399 tf_iov[0].iov_base = (void *)tf;
400 tf_iov[0].iov_len = tf_len;
401 tf_iov[1].iov_base = (void *)hdr;
402 tf_iov[1].iov_len = enc_len;
404 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
405 conn->protocol,
406 tf_iov, 2);
407 if (!NT_STATUS_IS_OK(status)) {
408 TALLOC_FREE(iov_alloc);
409 return status;
412 verified_buflen = taken + enc_len;
413 len = enc_len;
417 * We need the header plus the body length field
420 if (len < SMB2_HDR_BODY + 2) {
421 DEBUG(10, ("%d bytes left, expected at least %d\n",
422 (int)len, SMB2_HDR_BODY));
423 goto inval;
425 if (IVAL(hdr, 0) != SMB2_MAGIC) {
426 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
427 IVAL(hdr, 0)));
428 goto inval;
430 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
431 DEBUG(10, ("Got HDR len %d, expected %d\n",
432 SVAL(hdr, 4), SMB2_HDR_BODY));
433 goto inval;
436 full_size = len;
437 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
438 body_size = SVAL(hdr, SMB2_HDR_BODY);
440 if (next_command_ofs != 0) {
441 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
442 goto inval;
444 if (next_command_ofs > full_size) {
445 goto inval;
447 full_size = next_command_ofs;
449 if (body_size < 2) {
450 goto inval;
452 body_size &= 0xfffe;
454 if (body_size > (full_size - SMB2_HDR_BODY)) {
456 * let the caller handle the error
458 body_size = full_size - SMB2_HDR_BODY;
460 body = hdr + SMB2_HDR_BODY;
461 dyn = body + body_size;
462 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
464 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
465 struct iovec *iov_tmp = NULL;
467 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
468 struct iovec,
469 num_iov +
470 SMBD_SMB2_NUM_IOV_PER_REQ);
471 if (iov_tmp == NULL) {
472 TALLOC_FREE(iov_alloc);
473 return NT_STATUS_NO_MEMORY;
476 if (iov_alloc == NULL) {
477 memcpy(iov_tmp,
478 req->in._vector,
479 sizeof(req->in._vector));
482 iov = iov_tmp;
484 cur = &iov[num_iov];
485 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
487 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
488 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
489 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
490 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
491 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
492 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
493 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
494 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
496 taken += full_size;
499 *piov = iov;
500 *pnum_iov = num_iov;
501 return NT_STATUS_OK;
503 inval:
504 if (iov != req->in._vector) {
505 TALLOC_FREE(iov);
507 return NT_STATUS_INVALID_PARAMETER;
510 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
511 uint8_t *inbuf, size_t size,
512 struct smbd_smb2_request **_req)
514 struct smbd_smb2_request *req;
515 uint32_t protocol_version;
516 const uint8_t *inhdr = NULL;
517 uint16_t cmd;
518 uint32_t next_command_ofs;
519 NTSTATUS status;
520 NTTIME now;
522 if (size < (4 + SMB2_HDR_BODY + 2)) {
523 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
524 return NT_STATUS_INVALID_PARAMETER;
527 inhdr = inbuf + 4;
529 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
530 if (protocol_version != SMB2_MAGIC) {
531 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
532 protocol_version));
533 return NT_STATUS_INVALID_PARAMETER;
536 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
537 if (cmd != SMB2_OP_NEGPROT) {
538 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
539 cmd));
540 return NT_STATUS_INVALID_PARAMETER;
543 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
544 if (next_command_ofs != 0) {
545 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
546 next_command_ofs));
547 return NT_STATUS_INVALID_PARAMETER;
550 req = smbd_smb2_request_allocate(sconn);
551 if (req == NULL) {
552 return NT_STATUS_NO_MEMORY;
554 req->sconn = sconn;
556 talloc_steal(req, inbuf);
558 req->request_time = timeval_current();
559 now = timeval_to_nttime(&req->request_time);
561 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
562 now,
563 inbuf + NBT_HDR_SIZE,
564 size - NBT_HDR_SIZE,
565 req, &req->in.vector,
566 &req->in.vector_count);
567 if (!NT_STATUS_IS_OK(status)) {
568 TALLOC_FREE(req);
569 return status;
572 req->current_idx = 1;
574 *_req = req;
575 return NT_STATUS_OK;
578 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
579 uint64_t message_id, uint64_t seq_id)
581 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
582 unsigned int offset;
584 if (seq_id < sconn->smb2.seqnum_low) {
585 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
586 "%llu (sequence id %llu) "
587 "(granted = %u, low = %llu, range = %u)\n",
588 (unsigned long long)message_id,
589 (unsigned long long)seq_id,
590 (unsigned int)sconn->smb2.credits_granted,
591 (unsigned long long)sconn->smb2.seqnum_low,
592 (unsigned int)sconn->smb2.seqnum_range));
593 return false;
596 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
597 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
598 "%llu (sequence id %llu) "
599 "(granted = %u, low = %llu, range = %u)\n",
600 (unsigned long long)message_id,
601 (unsigned long long)seq_id,
602 (unsigned int)sconn->smb2.credits_granted,
603 (unsigned long long)sconn->smb2.seqnum_low,
604 (unsigned int)sconn->smb2.seqnum_range));
605 return false;
608 offset = seq_id % sconn->smb2.max_credits;
610 if (bitmap_query(credits_bm, offset)) {
611 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
612 "%llu (sequence id %llu) "
613 "(granted = %u, low = %llu, range = %u) "
614 "(bm offset %u)\n",
615 (unsigned long long)message_id,
616 (unsigned long long)seq_id,
617 (unsigned int)sconn->smb2.credits_granted,
618 (unsigned long long)sconn->smb2.seqnum_low,
619 (unsigned int)sconn->smb2.seqnum_range,
620 offset));
621 return false;
624 /* Mark the message_ids as seen in the bitmap. */
625 bitmap_set(credits_bm, offset);
627 if (seq_id != sconn->smb2.seqnum_low) {
628 return true;
632 * Move the window forward by all the message_id's
633 * already seen.
635 while (bitmap_query(credits_bm, offset)) {
636 DEBUG(10,("smb2_validate_sequence_number: clearing "
637 "id %llu (position %u) from bitmap\n",
638 (unsigned long long)(sconn->smb2.seqnum_low),
639 offset));
640 bitmap_clear(credits_bm, offset);
642 sconn->smb2.seqnum_low += 1;
643 sconn->smb2.seqnum_range -= 1;
644 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
647 return true;
650 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
651 const uint8_t *inhdr)
653 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
654 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
655 uint16_t credit_charge = 1;
656 uint64_t i;
658 if (opcode == SMB2_OP_CANCEL) {
659 /* SMB2_CANCEL requests by definition resend messageids. */
660 return true;
663 if (sconn->smb2.supports_multicredit) {
664 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
665 credit_charge = MAX(credit_charge, 1);
668 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
669 "credits_granted %llu, "
670 "seqnum low/range: %llu/%llu\n",
671 (unsigned long long) message_id,
672 (unsigned long long) credit_charge,
673 (unsigned long long) sconn->smb2.credits_granted,
674 (unsigned long long) sconn->smb2.seqnum_low,
675 (unsigned long long) sconn->smb2.seqnum_range));
677 if (sconn->smb2.credits_granted < credit_charge) {
678 DEBUG(0, ("smb2_validate_message_id: client used more "
679 "credits than granted, mid %llu, charge %llu, "
680 "credits_granted %llu, "
681 "seqnum low/range: %llu/%llu\n",
682 (unsigned long long) message_id,
683 (unsigned long long) credit_charge,
684 (unsigned long long) sconn->smb2.credits_granted,
685 (unsigned long long) sconn->smb2.seqnum_low,
686 (unsigned long long) sconn->smb2.seqnum_range));
687 return false;
691 * now check the message ids
693 * for multi-credit requests we need to check all current mid plus
694 * the implicit mids caused by the credit charge
695 * e.g. current mid = 15, charge 5 => mark 15-19 as used
698 for (i = 0; i <= (credit_charge-1); i++) {
699 uint64_t id = message_id + i;
700 bool ok;
702 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
703 (unsigned long long)message_id,
704 credit_charge,
705 (unsigned long long)id));
707 ok = smb2_validate_sequence_number(sconn, message_id, id);
708 if (!ok) {
709 return false;
713 /* substract used credits */
714 sconn->smb2.credits_granted -= credit_charge;
716 return true;
719 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
721 int count;
722 int idx;
724 count = req->in.vector_count;
726 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
727 /* It's not a SMB2 request */
728 return NT_STATUS_INVALID_PARAMETER;
731 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
732 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
733 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
734 const uint8_t *inhdr = NULL;
736 if (hdr->iov_len != SMB2_HDR_BODY) {
737 return NT_STATUS_INVALID_PARAMETER;
740 if (body->iov_len < 2) {
741 return NT_STATUS_INVALID_PARAMETER;
744 inhdr = (const uint8_t *)hdr->iov_base;
746 /* Check the SMB2 header */
747 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
748 return NT_STATUS_INVALID_PARAMETER;
751 if (!smb2_validate_message_id(req->sconn, inhdr)) {
752 return NT_STATUS_INVALID_PARAMETER;
756 return NT_STATUS_OK;
759 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
760 const struct iovec *in_vector,
761 struct iovec *out_vector)
763 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
764 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
765 uint16_t credit_charge = 1;
766 uint16_t credits_requested;
767 uint32_t out_flags;
768 uint16_t cmd;
769 NTSTATUS out_status;
770 uint16_t credits_granted = 0;
771 uint64_t credits_possible;
772 uint16_t current_max_credits;
775 * first we grant only 1/16th of the max range.
777 * Windows also starts with the 1/16th and then grants
778 * more later. I was only able to trigger higher
779 * values, when using a very high credit charge.
781 * TODO: scale up depending on load, free memory
782 * or other stuff.
783 * Maybe also on the relationship between number
784 * of requests and the used sequence number.
785 * Which means we would grant more credits
786 * for client which use multi credit requests.
788 current_max_credits = sconn->smb2.max_credits / 16;
789 current_max_credits = MAX(current_max_credits, 1);
791 if (sconn->smb2.supports_multicredit) {
792 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
793 credit_charge = MAX(credit_charge, 1);
796 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
797 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
798 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
799 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
801 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
803 if (sconn->smb2.max_credits < credit_charge) {
804 smbd_server_connection_terminate(sconn,
805 "client error: credit charge > max credits\n");
806 return;
809 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
811 * In case we already send an async interim
812 * response, we should not grant
813 * credits on the final response.
815 credits_granted = 0;
816 } else if (credits_requested > 0) {
817 uint16_t additional_max = 0;
818 uint16_t additional_credits = credits_requested - 1;
820 switch (cmd) {
821 case SMB2_OP_NEGPROT:
822 break;
823 case SMB2_OP_SESSSETUP:
825 * Windows 2012 RC1 starts to grant
826 * additional credits
827 * with a successful session setup
829 if (NT_STATUS_IS_OK(out_status)) {
830 additional_max = 32;
832 break;
833 default:
835 * We match windows and only grant additional credits
836 * in chunks of 32.
838 additional_max = 32;
839 break;
842 additional_credits = MIN(additional_credits, additional_max);
844 credits_granted = credit_charge + additional_credits;
845 } else if (sconn->smb2.credits_granted == 0) {
847 * Make sure the client has always at least one credit
849 credits_granted = 1;
853 * sequence numbers should not wrap
855 * 1. calculate the possible credits until
856 * the sequence numbers start to wrap on 64-bit.
858 * 2. UINT64_MAX is used for Break Notifications.
860 * 2. truncate the possible credits to the maximum
861 * credits we want to grant to the client in total.
863 * 3. remove the range we'll already granted to the client
864 * this makes sure the client consumes the lowest sequence
865 * number, before we can grant additional credits.
867 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
868 if (credits_possible > 0) {
869 /* remove UINT64_MAX */
870 credits_possible -= 1;
872 credits_possible = MIN(credits_possible, current_max_credits);
873 credits_possible -= sconn->smb2.seqnum_range;
875 credits_granted = MIN(credits_granted, credits_possible);
877 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
878 sconn->smb2.credits_granted += credits_granted;
879 sconn->smb2.seqnum_range += credits_granted;
881 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
882 "granted %u, current possible/max %u/%u, "
883 "total granted/max/low/range %u/%u/%llu/%u\n",
884 (unsigned int)credits_requested,
885 (unsigned int)credit_charge,
886 (unsigned int)credits_granted,
887 (unsigned int)credits_possible,
888 (unsigned int)current_max_credits,
889 (unsigned int)sconn->smb2.credits_granted,
890 (unsigned int)sconn->smb2.max_credits,
891 (unsigned long long)sconn->smb2.seqnum_low,
892 (unsigned int)sconn->smb2.seqnum_range));
895 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
896 struct smbd_smb2_request *outreq)
898 int count, idx;
899 uint16_t total_credits = 0;
901 count = outreq->out.vector_count;
903 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
904 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
905 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
906 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
908 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
910 /* To match Windows, count up what we
911 just granted. */
912 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
913 /* Set to zero in all but the last reply. */
914 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
915 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
916 } else {
917 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
922 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
924 if (req->current_idx <= 1) {
925 if (size <= sizeof(req->out._body)) {
926 return data_blob_const(req->out._body, size);
930 return data_blob_talloc(req, NULL, size);
933 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
935 TALLOC_CTX *mem_ctx;
936 struct iovec *vector;
937 int count;
938 int idx;
940 count = req->in.vector_count;
941 if (count <= ARRAY_SIZE(req->out._vector)) {
942 mem_ctx = req;
943 vector = req->out._vector;
944 } else {
945 vector = talloc_zero_array(req, struct iovec, count);
946 if (vector == NULL) {
947 return NT_STATUS_NO_MEMORY;
949 mem_ctx = vector;
952 vector[0].iov_base = req->out.nbt_hdr;
953 vector[0].iov_len = 4;
954 SIVAL(req->out.nbt_hdr, 0, 0);
956 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
957 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
958 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
959 uint8_t *outhdr = NULL;
960 uint8_t *outbody = NULL;
961 uint32_t next_command_ofs = 0;
962 struct iovec *current = &vector[idx];
964 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
965 /* we have a next command -
966 * setup for the error case. */
967 next_command_ofs = SMB2_HDR_BODY + 9;
970 if (idx == 1) {
971 outhdr = req->out._hdr;
972 } else {
973 outhdr = talloc_zero_array(mem_ctx, uint8_t,
974 OUTVEC_ALLOC_SIZE);
975 if (outhdr == NULL) {
976 return NT_STATUS_NO_MEMORY;
980 outbody = outhdr + SMB2_HDR_BODY;
983 * SMBD_SMB2_TF_IOV_OFS might be used later
985 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
986 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
988 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
989 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
991 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
992 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
994 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
995 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
997 /* setup the SMB2 header */
998 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
999 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1000 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1001 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1002 SIVAL(outhdr, SMB2_HDR_STATUS,
1003 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1004 SSVAL(outhdr, SMB2_HDR_OPCODE,
1005 SVAL(inhdr, SMB2_HDR_OPCODE));
1006 SIVAL(outhdr, SMB2_HDR_FLAGS,
1007 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1008 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1009 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1010 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1011 SIVAL(outhdr, SMB2_HDR_PID,
1012 IVAL(inhdr, SMB2_HDR_PID));
1013 SIVAL(outhdr, SMB2_HDR_TID,
1014 IVAL(inhdr, SMB2_HDR_TID));
1015 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1016 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1017 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1018 inhdr + SMB2_HDR_SIGNATURE, 16);
1020 /* setup error body header */
1021 SSVAL(outbody, 0x00, 0x08 + 1);
1022 SSVAL(outbody, 0x02, 0);
1023 SIVAL(outbody, 0x04, 0);
1026 req->out.vector = vector;
1027 req->out.vector_count = count;
1029 /* setup the length of the NBT packet */
1030 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1032 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1034 return NT_STATUS_OK;
1037 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1038 const char *reason,
1039 const char *location)
1041 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1042 reason, location));
1043 exit_server_cleanly(reason);
1046 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1047 struct iovec *outvec,
1048 const struct iovec *srcvec)
1050 const uint8_t *srctf;
1051 size_t srctf_len;
1052 const uint8_t *srchdr;
1053 size_t srchdr_len;
1054 const uint8_t *srcbody;
1055 size_t srcbody_len;
1056 const uint8_t *expected_srcbody;
1057 const uint8_t *srcdyn;
1058 size_t srcdyn_len;
1059 const uint8_t *expected_srcdyn;
1060 uint8_t *dsttf;
1061 uint8_t *dsthdr;
1062 uint8_t *dstbody;
1063 uint8_t *dstdyn;
1065 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1066 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1067 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1068 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1069 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1070 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1071 expected_srcbody = srchdr + SMB2_HDR_BODY;
1072 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1073 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1074 expected_srcdyn = srcbody + 8;
1076 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1077 return false;
1080 if (srchdr_len != SMB2_HDR_BODY) {
1081 return false;
1084 if (srctf_len == SMB2_TF_HDR_SIZE) {
1085 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1086 if (dsttf == NULL) {
1087 return false;
1089 } else {
1090 dsttf = NULL;
1092 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1093 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1095 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1096 * be allocated with size OUTVEC_ALLOC_SIZE. */
1098 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1099 if (dsthdr == NULL) {
1100 return false;
1102 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1103 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1106 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1107 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1108 * then duplicate this. Else use talloc_memdup().
1111 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1112 dstbody = dsthdr + SMB2_HDR_BODY;
1113 } else {
1114 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1115 if (dstbody == NULL) {
1116 return false;
1119 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1120 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1123 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1124 * pointing to
1125 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1126 * then duplicate this. Else use talloc_memdup().
1129 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1130 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1131 } else if (srcdyn == NULL) {
1132 dstdyn = NULL;
1133 } else {
1134 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1135 if (dstdyn == NULL) {
1136 return false;
1139 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1140 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1142 return true;
1145 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1147 struct smbd_smb2_request *newreq = NULL;
1148 struct iovec *outvec = NULL;
1149 int count = req->out.vector_count;
1150 int i;
1152 newreq = smbd_smb2_request_allocate(req->sconn);
1153 if (!newreq) {
1154 return NULL;
1157 newreq->sconn = req->sconn;
1158 newreq->session = req->session;
1159 newreq->do_encryption = req->do_encryption;
1160 newreq->do_signing = req->do_signing;
1161 newreq->current_idx = req->current_idx;
1163 outvec = talloc_zero_array(newreq, struct iovec, count);
1164 if (!outvec) {
1165 TALLOC_FREE(newreq);
1166 return NULL;
1168 newreq->out.vector = outvec;
1169 newreq->out.vector_count = count;
1171 /* Setup the outvec's identically to req. */
1172 outvec[0].iov_base = newreq->out.nbt_hdr;
1173 outvec[0].iov_len = 4;
1174 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1176 /* Setup the vectors identically to the ones in req. */
1177 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1178 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1179 break;
1183 if (i < count) {
1184 /* Alloc failed. */
1185 TALLOC_FREE(newreq);
1186 return NULL;
1189 smb2_setup_nbt_length(newreq->out.vector,
1190 newreq->out.vector_count);
1192 return newreq;
1195 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1197 struct smbd_server_connection *sconn = req->sconn;
1198 struct smbXsrv_connection *conn = req->sconn->conn;
1199 int first_idx = 1;
1200 struct iovec *firsttf = NULL;
1201 struct iovec *outhdr_v = NULL;
1202 uint8_t *outhdr = NULL;
1203 struct smbd_smb2_request *nreq = NULL;
1204 NTSTATUS status;
1206 /* Create a new smb2 request we'll use
1207 for the interim return. */
1208 nreq = dup_smb2_req(req);
1209 if (!nreq) {
1210 return NT_STATUS_NO_MEMORY;
1213 /* Lose the last X out vectors. They're the
1214 ones we'll be using for the async reply. */
1215 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1217 smb2_setup_nbt_length(nreq->out.vector,
1218 nreq->out.vector_count);
1220 /* Step back to the previous reply. */
1221 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1222 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1223 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1224 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1225 /* And end the chain. */
1226 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1228 /* Calculate outgoing credits */
1229 smb2_calculate_credits(req, nreq);
1231 if (DEBUGLEVEL >= 10) {
1232 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1233 (unsigned int)nreq->current_idx );
1234 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1235 (unsigned int)nreq->out.vector_count );
1236 print_req_vectors(nreq);
1240 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1241 * we need to sign/encrypt here with the last/first key we remembered
1243 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1244 status = smb2_signing_encrypt_pdu(req->first_key,
1245 conn->protocol,
1246 firsttf,
1247 nreq->out.vector_count - first_idx);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 return status;
1251 } else if (req->last_key.length > 0) {
1252 status = smb2_signing_sign_pdu(req->last_key,
1253 conn->protocol,
1254 outhdr_v,
1255 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1261 nreq->queue_entry.mem_ctx = nreq;
1262 nreq->queue_entry.vector = nreq->out.vector;
1263 nreq->queue_entry.count = nreq->out.vector_count;
1264 DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1265 nreq->sconn->smb2.send_queue_len++;
1267 status = smbd_smb2_flush_send_queue(sconn);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 return status;
1272 return NT_STATUS_OK;
1275 struct smbd_smb2_request_pending_state {
1276 struct smbd_server_connection *sconn;
1277 struct smbd_smb2_send_queue queue_entry;
1278 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1279 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1282 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1283 struct tevent_timer *te,
1284 struct timeval current_time,
1285 void *private_data);
1287 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1288 struct tevent_req *subreq,
1289 uint32_t defer_time)
1291 NTSTATUS status;
1292 struct timeval defer_endtime;
1293 uint8_t *outhdr = NULL;
1294 uint32_t flags;
1296 if (!tevent_req_is_in_progress(subreq)) {
1298 * This is a performance optimization,
1299 * it avoids one tevent_loop iteration,
1300 * which means we avoid one
1301 * talloc_stackframe_pool/talloc_free pair.
1303 tevent_req_notify_callback(subreq);
1304 return NT_STATUS_OK;
1307 req->subreq = subreq;
1308 subreq = NULL;
1310 if (req->async_te) {
1311 /* We're already async. */
1312 return NT_STATUS_OK;
1315 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1316 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1317 if (flags & SMB2_HDR_FLAG_ASYNC) {
1318 /* We're already async. */
1319 return NT_STATUS_OK;
1322 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1324 * We're trying to go async in a compound
1325 * request chain.
1326 * This is only allowed for opens that
1327 * cause an oplock break, otherwise it
1328 * is not allowed. See [MS-SMB2].pdf
1329 * note <194> on Section 3.3.5.2.7.
1331 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1333 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1335 * Cancel the outstanding request.
1337 bool ok = tevent_req_cancel(req->subreq);
1338 if (ok) {
1339 return NT_STATUS_OK;
1341 TALLOC_FREE(req->subreq);
1342 return smbd_smb2_request_error(req,
1343 NT_STATUS_INTERNAL_ERROR);
1347 if (DEBUGLEVEL >= 10) {
1348 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1349 (unsigned int)req->current_idx );
1350 print_req_vectors(req);
1353 if (req->current_idx > 1) {
1355 * We're going async in a compound
1356 * chain after the first request has
1357 * already been processed. Send an
1358 * interim response containing the
1359 * set of replies already generated.
1361 int idx = req->current_idx;
1363 status = smb2_send_async_interim_response(req);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 return status;
1367 if (req->first_key.length > 0) {
1368 data_blob_clear_free(&req->first_key);
1371 req->current_idx = 1;
1374 * Re-arrange the in.vectors to remove what
1375 * we just sent.
1377 memmove(&req->in.vector[1],
1378 &req->in.vector[idx],
1379 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1380 req->in.vector_count = 1 + (req->in.vector_count - idx);
1382 /* Re-arrange the out.vectors to match. */
1383 memmove(&req->out.vector[1],
1384 &req->out.vector[idx],
1385 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1386 req->out.vector_count = 1 + (req->out.vector_count - idx);
1388 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1390 * We only have one remaining request as
1391 * we've processed everything else.
1392 * This is no longer a compound request.
1394 req->compound_related = false;
1395 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1396 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1397 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1400 if (req->last_key.length > 0) {
1401 data_blob_clear_free(&req->last_key);
1404 defer_endtime = timeval_current_ofs_usec(defer_time);
1405 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1406 req, defer_endtime,
1407 smbd_smb2_request_pending_timer,
1408 req);
1409 if (req->async_te == NULL) {
1410 return NT_STATUS_NO_MEMORY;
1413 return NT_STATUS_OK;
1416 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1417 struct tevent_timer *te,
1418 struct timeval current_time,
1419 void *private_data)
1421 struct smbd_smb2_request *req =
1422 talloc_get_type_abort(private_data,
1423 struct smbd_smb2_request);
1424 struct smbd_server_connection *sconn = req->sconn;
1425 struct smbd_smb2_request_pending_state *state = NULL;
1426 uint8_t *outhdr = NULL;
1427 const uint8_t *inhdr = NULL;
1428 uint8_t *tf = NULL;
1429 size_t tf_len = 0;
1430 uint8_t *hdr = NULL;
1431 uint8_t *body = NULL;
1432 uint8_t *dyn = NULL;
1433 uint32_t flags = 0;
1434 uint64_t session_id = 0;
1435 uint64_t message_id = 0;
1436 uint64_t nonce_high = 0;
1437 uint64_t nonce_low = 0;
1438 uint64_t async_id = 0;
1439 NTSTATUS status;
1441 TALLOC_FREE(req->async_te);
1443 /* Ensure our final reply matches the interim one. */
1444 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1445 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1446 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1447 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1448 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1450 async_id = message_id; /* keep it simple for now... */
1452 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1453 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1455 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1456 "going async\n",
1457 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1458 (unsigned long long)async_id ));
1461 * What we send is identical to a smbd_smb2_request_error
1462 * packet with an error status of STATUS_PENDING. Make use
1463 * of this fact sometime when refactoring. JRA.
1466 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1467 if (state == NULL) {
1468 smbd_server_connection_terminate(req->sconn,
1469 nt_errstr(NT_STATUS_NO_MEMORY));
1470 return;
1472 state->sconn = req->sconn;
1474 tf = state->buf + NBT_HDR_SIZE;
1475 tf_len = SMB2_TF_HDR_SIZE;
1477 hdr = tf + SMB2_TF_HDR_SIZE;
1478 body = hdr + SMB2_HDR_BODY;
1479 dyn = body + 8;
1481 if (req->do_encryption) {
1482 struct smbXsrv_session *x = req->session;
1484 nonce_high = x->nonce_high;
1485 nonce_low = x->nonce_low;
1487 x->nonce_low += 1;
1488 if (x->nonce_low == 0) {
1489 x->nonce_low += 1;
1490 x->nonce_high += 1;
1494 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1495 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1496 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1497 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1499 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1500 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1501 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1502 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1503 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1505 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1506 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1507 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1508 SBVAL(hdr, SMB2_HDR_PID, async_id);
1509 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1510 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1511 memcpy(hdr+SMB2_HDR_SIGNATURE,
1512 outhdr+SMB2_HDR_SIGNATURE, 16);
1514 SSVAL(body, 0x00, 0x08 + 1);
1516 SCVAL(body, 0x02, 0);
1517 SCVAL(body, 0x03, 0);
1518 SIVAL(body, 0x04, 0);
1519 /* Match W2K8R2... */
1520 SCVAL(dyn, 0x00, 0x21);
1522 state->vector[0].iov_base = (void *)state->buf;
1523 state->vector[0].iov_len = NBT_HDR_SIZE;
1525 if (req->do_encryption) {
1526 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1527 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1528 } else {
1529 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1530 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1533 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1534 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1536 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1537 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1539 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1540 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1542 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1544 /* Ensure we correctly go through crediting. Grant
1545 the credits now, and zero credits on the final
1546 response. */
1547 smb2_set_operation_credit(req->sconn,
1548 SMBD_SMB2_IN_HDR_IOV(req),
1549 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1551 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1553 if (DEBUGLVL(10)) {
1554 int i;
1556 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1557 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1558 (unsigned int)i,
1559 (unsigned int)ARRAY_SIZE(state->vector),
1560 (unsigned int)state->vector[i].iov_len);
1564 if (req->do_encryption) {
1565 struct smbXsrv_session *x = req->session;
1566 struct smbXsrv_connection *conn = x->connection;
1567 DATA_BLOB encryption_key = x->global->encryption_key;
1569 status = smb2_signing_encrypt_pdu(encryption_key,
1570 conn->protocol,
1571 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1572 SMBD_SMB2_NUM_IOV_PER_REQ);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 smbd_server_connection_terminate(req->sconn,
1575 nt_errstr(status));
1576 return;
1578 } else if (req->do_signing) {
1579 struct smbXsrv_session *x = req->session;
1580 struct smbXsrv_connection *conn = x->connection;
1581 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1583 status = smb2_signing_sign_pdu(signing_key,
1584 conn->protocol,
1585 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1586 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1587 if (!NT_STATUS_IS_OK(status)) {
1588 smbd_server_connection_terminate(req->sconn,
1589 nt_errstr(status));
1590 return;
1594 state->queue_entry.mem_ctx = state;
1595 state->queue_entry.vector = state->vector;
1596 state->queue_entry.count = ARRAY_SIZE(state->vector);
1597 DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1598 sconn->smb2.send_queue_len++;
1600 status = smbd_smb2_flush_send_queue(sconn);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 smbd_server_connection_terminate(sconn,
1603 nt_errstr(status));
1604 return;
1608 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1610 struct smbd_server_connection *sconn = req->sconn;
1611 struct smbd_smb2_request *cur;
1612 const uint8_t *inhdr;
1613 uint32_t flags;
1614 uint64_t search_message_id;
1615 uint64_t search_async_id;
1616 uint64_t found_id;
1618 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1620 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1621 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1622 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1625 * we don't need the request anymore
1626 * cancel requests never have a response
1628 DLIST_REMOVE(req->sconn->smb2.requests, req);
1629 TALLOC_FREE(req);
1631 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1632 const uint8_t *outhdr;
1633 uint64_t message_id;
1634 uint64_t async_id;
1636 if (cur->compound_related) {
1638 * Never cancel anything in a compound request.
1639 * Way too hard to deal with the result.
1641 continue;
1644 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1646 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1647 async_id = BVAL(outhdr, SMB2_HDR_PID);
1649 if (flags & SMB2_HDR_FLAG_ASYNC) {
1650 if (search_async_id == async_id) {
1651 found_id = async_id;
1652 break;
1654 } else {
1655 if (search_message_id == message_id) {
1656 found_id = message_id;
1657 break;
1662 if (cur && cur->subreq) {
1663 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1664 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1665 "cancel opcode[%s] mid %llu\n",
1666 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1667 (unsigned long long)found_id ));
1668 tevent_req_cancel(cur->subreq);
1671 return NT_STATUS_OK;
1674 /*************************************************************
1675 Ensure an incoming tid is a valid one for us to access.
1676 Change to the associated uid credentials and chdir to the
1677 valid tid directory.
1678 *************************************************************/
1680 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1682 const uint8_t *inhdr;
1683 uint32_t in_flags;
1684 uint32_t in_tid;
1685 struct smbXsrv_tcon *tcon;
1686 NTSTATUS status;
1687 NTTIME now = timeval_to_nttime(&req->request_time);
1689 req->tcon = NULL;
1691 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1693 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1694 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1696 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1697 in_tid = req->last_tid;
1700 req->last_tid = 0;
1702 status = smb2srv_tcon_lookup(req->session,
1703 in_tid, now, &tcon);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 return status;
1708 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1709 return NT_STATUS_ACCESS_DENIED;
1712 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1713 if (!set_current_service(tcon->compat, 0, true)) {
1714 return NT_STATUS_ACCESS_DENIED;
1717 req->tcon = tcon;
1718 req->last_tid = in_tid;
1720 return NT_STATUS_OK;
1723 /*************************************************************
1724 Ensure an incoming session_id is a valid one for us to access.
1725 *************************************************************/
1727 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1729 const uint8_t *inhdr;
1730 uint32_t in_flags;
1731 uint16_t in_opcode;
1732 uint64_t in_session_id;
1733 struct smbXsrv_session *session = NULL;
1734 struct auth_session_info *session_info;
1735 NTSTATUS status;
1736 NTTIME now = timeval_to_nttime(&req->request_time);
1738 req->session = NULL;
1739 req->tcon = NULL;
1741 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1743 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1744 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1745 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1747 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1748 in_session_id = req->last_session_id;
1751 req->last_session_id = 0;
1753 /* lookup an existing session */
1754 status = smb2srv_session_lookup(req->sconn->conn,
1755 in_session_id, now,
1756 &session);
1757 if (session) {
1758 req->session = session;
1759 req->last_session_id = in_session_id;
1761 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1762 switch (in_opcode) {
1763 case SMB2_OP_SESSSETUP:
1764 status = NT_STATUS_OK;
1765 break;
1766 default:
1767 break;
1770 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1771 switch (in_opcode) {
1772 case SMB2_OP_TCON:
1773 case SMB2_OP_CREATE:
1774 case SMB2_OP_GETINFO:
1775 case SMB2_OP_SETINFO:
1776 return NT_STATUS_INVALID_HANDLE;
1777 default:
1779 * Notice the check for
1780 * (session_info == NULL)
1781 * below.
1783 status = NT_STATUS_OK;
1784 break;
1787 if (!NT_STATUS_IS_OK(status)) {
1788 return status;
1791 session_info = session->global->auth_session_info;
1792 if (session_info == NULL) {
1793 return NT_STATUS_INVALID_HANDLE;
1796 if (in_session_id != req->sconn->conn->last_session_id) {
1797 req->sconn->conn->last_session_id = in_session_id;
1798 set_current_user_info(session_info->unix_info->sanitized_username,
1799 session_info->unix_info->unix_name,
1800 session_info->info->domain_name);
1803 return NT_STATUS_OK;
1806 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1807 uint32_t data_length)
1809 uint16_t needed_charge;
1810 uint16_t credit_charge = 1;
1811 const uint8_t *inhdr;
1813 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1815 if (req->sconn->smb2.supports_multicredit) {
1816 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1817 credit_charge = MAX(credit_charge, 1);
1820 needed_charge = (data_length - 1)/ 65536 + 1;
1822 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1823 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1824 credit_charge, needed_charge));
1826 if (needed_charge > credit_charge) {
1827 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1828 credit_charge, needed_charge));
1829 return NT_STATUS_INVALID_PARAMETER;
1832 return NT_STATUS_OK;
1835 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1836 size_t expected_body_size)
1838 struct iovec *inhdr_v;
1839 const uint8_t *inhdr;
1840 uint16_t opcode;
1841 const uint8_t *inbody;
1842 size_t body_size;
1843 size_t min_dyn_size = expected_body_size & 0x00000001;
1844 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1847 * The following should be checked already.
1849 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1850 return NT_STATUS_INTERNAL_ERROR;
1852 if (req->current_idx > max_idx) {
1853 return NT_STATUS_INTERNAL_ERROR;
1856 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1857 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1858 return NT_STATUS_INTERNAL_ERROR;
1860 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1861 return NT_STATUS_INTERNAL_ERROR;
1864 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1865 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1867 switch (opcode) {
1868 case SMB2_OP_IOCTL:
1869 case SMB2_OP_GETINFO:
1870 min_dyn_size = 0;
1871 break;
1872 case SMB2_OP_WRITE:
1873 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1874 if (req->smb1req->unread_bytes < min_dyn_size) {
1875 return NT_STATUS_INVALID_PARAMETER;
1878 min_dyn_size = 0;
1880 break;
1884 * Now check the expected body size,
1885 * where the last byte might be in the
1886 * dynamic section..
1888 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1889 return NT_STATUS_INVALID_PARAMETER;
1891 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1892 return NT_STATUS_INVALID_PARAMETER;
1895 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1897 body_size = SVAL(inbody, 0x00);
1898 if (body_size != expected_body_size) {
1899 return NT_STATUS_INVALID_PARAMETER;
1902 return NT_STATUS_OK;
1905 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1907 struct smbXsrv_connection *conn = req->sconn->conn;
1908 const struct smbd_smb2_dispatch_table *call = NULL;
1909 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1910 const uint8_t *inhdr;
1911 uint16_t opcode;
1912 uint32_t flags;
1913 uint64_t mid;
1914 NTSTATUS status;
1915 NTSTATUS session_status;
1916 uint32_t allowed_flags;
1917 NTSTATUS return_value;
1918 struct smbXsrv_session *x = NULL;
1919 bool signing_required = false;
1920 bool encryption_required = false;
1922 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1924 /* TODO: verify more things */
1926 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1927 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1928 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1929 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1930 smb2_opcode_name(opcode),
1931 (unsigned long long)mid));
1933 if (conn->protocol >= PROTOCOL_SMB2_02) {
1935 * once the protocol is negotiated
1936 * SMB2_OP_NEGPROT is not allowed anymore
1938 if (opcode == SMB2_OP_NEGPROT) {
1939 /* drop the connection */
1940 return NT_STATUS_INVALID_PARAMETER;
1942 } else {
1944 * if the protocol is not negotiated yet
1945 * only SMB2_OP_NEGPROT is allowed.
1947 if (opcode != SMB2_OP_NEGPROT) {
1948 /* drop the connection */
1949 return NT_STATUS_INVALID_PARAMETER;
1954 * Check if the client provided a valid session id,
1955 * if so smbd_smb2_request_check_session() calls
1956 * set_current_user_info().
1958 * As some command don't require a valid session id
1959 * we defer the check of the session_status
1961 session_status = smbd_smb2_request_check_session(req);
1962 x = req->session;
1963 if (x != NULL) {
1964 signing_required = x->global->signing_required;
1965 encryption_required = x->global->encryption_required;
1967 if (opcode == SMB2_OP_SESSSETUP &&
1968 x->global->channels[0].signing_key.length) {
1969 signing_required = true;
1973 req->do_signing = false;
1974 req->do_encryption = false;
1975 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1976 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1977 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1979 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1980 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1981 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1982 (unsigned long long)x->global->session_wire_id,
1983 (unsigned long long)tf_session_id));
1985 * TODO: windows allows this...
1986 * should we drop the connection?
1988 * For now we just return ACCESS_DENIED
1989 * (Windows clients never trigger this)
1990 * and wait for an update of [MS-SMB2].
1992 return smbd_smb2_request_error(req,
1993 NT_STATUS_ACCESS_DENIED);
1996 req->do_encryption = true;
1999 if (encryption_required && !req->do_encryption) {
2000 return smbd_smb2_request_error(req,
2001 NT_STATUS_ACCESS_DENIED);
2004 call = smbd_smb2_call(opcode);
2005 if (call == NULL) {
2006 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2009 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2010 SMB2_HDR_FLAG_SIGNED |
2011 SMB2_HDR_FLAG_DFS;
2012 if (opcode == SMB2_OP_CANCEL) {
2013 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2015 if ((flags & ~allowed_flags) != 0) {
2016 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2019 if (flags & SMB2_HDR_FLAG_CHAINED) {
2021 * This check is mostly for giving the correct error code
2022 * for compounded requests.
2024 if (!NT_STATUS_IS_OK(session_status)) {
2025 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2027 } else {
2028 req->compat_chain_fsp = NULL;
2031 if (req->do_encryption) {
2032 signing_required = false;
2033 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2034 DATA_BLOB signing_key;
2036 if (x == NULL) {
2038 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2039 * If the SMB2 header of the SMB2 NEGOTIATE
2040 * request has the SMB2_FLAGS_SIGNED bit set in the
2041 * Flags field, the server MUST fail the request
2042 * with STATUS_INVALID_PARAMETER.
2044 * Microsoft test tool checks this.
2047 if ((opcode == SMB2_OP_NEGPROT) &&
2048 (flags & SMB2_HDR_FLAG_SIGNED)) {
2049 status = NT_STATUS_INVALID_PARAMETER;
2050 } else {
2051 status = NT_STATUS_USER_SESSION_DELETED;
2053 return smbd_smb2_request_error(req, status);
2056 signing_key = x->global->channels[0].signing_key;
2059 * If we have a signing key, we should
2060 * sign the response
2062 if (signing_key.length > 0) {
2063 req->do_signing = true;
2066 status = smb2_signing_check_pdu(signing_key,
2067 conn->protocol,
2068 SMBD_SMB2_IN_HDR_IOV(req),
2069 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 return smbd_smb2_request_error(req, status);
2075 * Now that we know the request was correctly signed
2076 * we have to sign the response too.
2078 req->do_signing = true;
2080 if (!NT_STATUS_IS_OK(session_status)) {
2081 return smbd_smb2_request_error(req, session_status);
2083 } else if (opcode == SMB2_OP_CANCEL) {
2084 /* Cancel requests are allowed to skip the signing */
2085 } else if (signing_required) {
2087 * If signing is required we try to sign
2088 * a possible error response
2090 req->do_signing = true;
2091 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2094 if (flags & SMB2_HDR_FLAG_CHAINED) {
2095 req->compound_related = true;
2098 if (call->need_session) {
2099 if (!NT_STATUS_IS_OK(session_status)) {
2100 return smbd_smb2_request_error(req, session_status);
2104 if (call->need_tcon) {
2105 SMB_ASSERT(call->need_session);
2108 * This call needs to be run as user.
2110 * smbd_smb2_request_check_tcon()
2111 * calls change_to_user() on success.
2113 status = smbd_smb2_request_check_tcon(req);
2114 if (!NT_STATUS_IS_OK(status)) {
2115 return smbd_smb2_request_error(req, status);
2117 if (req->tcon->global->encryption_required) {
2118 encryption_required = true;
2120 if (encryption_required && !req->do_encryption) {
2121 return smbd_smb2_request_error(req,
2122 NT_STATUS_ACCESS_DENIED);
2126 if (call->fileid_ofs != 0) {
2127 size_t needed = call->fileid_ofs + 16;
2128 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2129 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2130 uint64_t file_id_persistent;
2131 uint64_t file_id_volatile;
2132 struct files_struct *fsp;
2134 SMB_ASSERT(call->need_tcon);
2136 if (needed > body_size) {
2137 return smbd_smb2_request_error(req,
2138 NT_STATUS_INVALID_PARAMETER);
2141 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2142 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2144 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2145 if (fsp == NULL) {
2146 if (!call->allow_invalid_fileid) {
2147 return smbd_smb2_request_error(req,
2148 NT_STATUS_FILE_CLOSED);
2151 if (file_id_persistent != UINT64_MAX) {
2152 return smbd_smb2_request_error(req,
2153 NT_STATUS_FILE_CLOSED);
2155 if (file_id_volatile != UINT64_MAX) {
2156 return smbd_smb2_request_error(req,
2157 NT_STATUS_FILE_CLOSED);
2162 if (call->as_root) {
2163 SMB_ASSERT(call->fileid_ofs == 0);
2164 /* This call needs to be run as root */
2165 change_to_root_user();
2166 } else {
2167 SMB_ASSERT(call->need_tcon);
2170 switch (opcode) {
2171 case SMB2_OP_NEGPROT:
2173 START_PROFILE(smb2_negprot);
2174 return_value = smbd_smb2_request_process_negprot(req);
2175 END_PROFILE(smb2_negprot);
2177 break;
2179 case SMB2_OP_SESSSETUP:
2181 START_PROFILE(smb2_sesssetup);
2182 return_value = smbd_smb2_request_process_sesssetup(req);
2183 END_PROFILE(smb2_sesssetup);
2185 break;
2187 case SMB2_OP_LOGOFF:
2189 START_PROFILE(smb2_logoff);
2190 return_value = smbd_smb2_request_process_logoff(req);
2191 END_PROFILE(smb2_logoff);
2193 break;
2195 case SMB2_OP_TCON:
2197 START_PROFILE(smb2_tcon);
2198 return_value = smbd_smb2_request_process_tcon(req);
2199 END_PROFILE(smb2_tcon);
2201 break;
2203 case SMB2_OP_TDIS:
2205 START_PROFILE(smb2_tdis);
2206 return_value = smbd_smb2_request_process_tdis(req);
2207 END_PROFILE(smb2_tdis);
2209 break;
2211 case SMB2_OP_CREATE:
2213 START_PROFILE(smb2_create);
2214 return_value = smbd_smb2_request_process_create(req);
2215 END_PROFILE(smb2_create);
2217 break;
2219 case SMB2_OP_CLOSE:
2221 START_PROFILE(smb2_close);
2222 return_value = smbd_smb2_request_process_close(req);
2223 END_PROFILE(smb2_close);
2225 break;
2227 case SMB2_OP_FLUSH:
2229 START_PROFILE(smb2_flush);
2230 return_value = smbd_smb2_request_process_flush(req);
2231 END_PROFILE(smb2_flush);
2233 break;
2235 case SMB2_OP_READ:
2237 START_PROFILE(smb2_read);
2238 return_value = smbd_smb2_request_process_read(req);
2239 END_PROFILE(smb2_read);
2241 break;
2243 case SMB2_OP_WRITE:
2245 START_PROFILE(smb2_write);
2246 return_value = smbd_smb2_request_process_write(req);
2247 END_PROFILE(smb2_write);
2249 break;
2251 case SMB2_OP_LOCK:
2253 START_PROFILE(smb2_lock);
2254 return_value = smbd_smb2_request_process_lock(req);
2255 END_PROFILE(smb2_lock);
2257 break;
2259 case SMB2_OP_IOCTL:
2261 START_PROFILE(smb2_ioctl);
2262 return_value = smbd_smb2_request_process_ioctl(req);
2263 END_PROFILE(smb2_ioctl);
2265 break;
2267 case SMB2_OP_CANCEL:
2269 START_PROFILE(smb2_cancel);
2270 return_value = smbd_smb2_request_process_cancel(req);
2271 END_PROFILE(smb2_cancel);
2273 break;
2275 case SMB2_OP_KEEPALIVE:
2277 START_PROFILE(smb2_keepalive);
2278 return_value = smbd_smb2_request_process_keepalive(req);
2279 END_PROFILE(smb2_keepalive);
2281 break;
2283 case SMB2_OP_FIND:
2285 START_PROFILE(smb2_find);
2286 return_value = smbd_smb2_request_process_find(req);
2287 END_PROFILE(smb2_find);
2289 break;
2291 case SMB2_OP_NOTIFY:
2293 START_PROFILE(smb2_notify);
2294 return_value = smbd_smb2_request_process_notify(req);
2295 END_PROFILE(smb2_notify);
2297 break;
2299 case SMB2_OP_GETINFO:
2301 START_PROFILE(smb2_getinfo);
2302 return_value = smbd_smb2_request_process_getinfo(req);
2303 END_PROFILE(smb2_getinfo);
2305 break;
2307 case SMB2_OP_SETINFO:
2309 START_PROFILE(smb2_setinfo);
2310 return_value = smbd_smb2_request_process_setinfo(req);
2311 END_PROFILE(smb2_setinfo);
2313 break;
2315 case SMB2_OP_BREAK:
2317 START_PROFILE(smb2_break);
2318 return_value = smbd_smb2_request_process_break(req);
2319 END_PROFILE(smb2_break);
2321 break;
2323 default:
2324 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2325 break;
2327 return return_value;
2330 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2332 struct smbd_server_connection *sconn = req->sconn;
2333 struct smbXsrv_connection *conn = req->sconn->conn;
2334 int first_idx = 1;
2335 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2336 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2337 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2338 NTSTATUS status;
2340 req->subreq = NULL;
2341 TALLOC_FREE(req->async_te);
2343 if (req->do_encryption &&
2344 (firsttf->iov_len == 0) &&
2345 (req->first_key.length == 0) &&
2346 (req->session != NULL) &&
2347 (req->session->global->encryption_key.length != 0))
2349 DATA_BLOB encryption_key = req->session->global->encryption_key;
2350 uint8_t *tf;
2351 uint64_t session_id = req->session->global->session_wire_id;
2352 struct smbXsrv_session *x = req->session;
2353 uint64_t nonce_high;
2354 uint64_t nonce_low;
2356 nonce_high = x->nonce_high;
2357 nonce_low = x->nonce_low;
2359 x->nonce_low += 1;
2360 if (x->nonce_low == 0) {
2361 x->nonce_low += 1;
2362 x->nonce_high += 1;
2366 * We need to place the SMB2_TRANSFORM header before the
2367 * first SMB2 header
2371 * we need to remember the encryption key
2372 * and defer the signing/encryption until
2373 * we are sure that we do not change
2374 * the header again.
2376 req->first_key = data_blob_dup_talloc(req, encryption_key);
2377 if (req->first_key.data == NULL) {
2378 return NT_STATUS_NO_MEMORY;
2381 tf = talloc_zero_array(req, uint8_t,
2382 SMB2_TF_HDR_SIZE);
2383 if (tf == NULL) {
2384 return NT_STATUS_NO_MEMORY;
2387 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2388 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2389 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2390 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2392 firsttf->iov_base = (void *)tf;
2393 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2396 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2397 (req->last_key.length > 0) &&
2398 (firsttf->iov_len == 0))
2400 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2401 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2404 * As we are sure the header of the last request in the
2405 * compound chain will not change, we can to sign here
2406 * with the last signing key we remembered.
2408 status = smb2_signing_sign_pdu(req->last_key,
2409 conn->protocol,
2410 lasthdr,
2411 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2412 if (!NT_STATUS_IS_OK(status)) {
2413 return status;
2416 if (req->last_key.length > 0) {
2417 data_blob_clear_free(&req->last_key);
2420 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2422 if (req->current_idx < req->out.vector_count) {
2424 * We must process the remaining compound
2425 * SMB2 requests before any new incoming SMB2
2426 * requests. This is because incoming SMB2
2427 * requests may include a cancel for a
2428 * compound request we haven't processed
2429 * yet.
2431 struct tevent_immediate *im = tevent_create_immediate(req);
2432 if (!im) {
2433 return NT_STATUS_NO_MEMORY;
2436 if (req->do_signing && firsttf->iov_len == 0) {
2437 struct smbXsrv_session *x = req->session;
2438 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2441 * we need to remember the signing key
2442 * and defer the signing until
2443 * we are sure that we do not change
2444 * the header again.
2446 req->last_key = data_blob_dup_talloc(req, signing_key);
2447 if (req->last_key.data == NULL) {
2448 return NT_STATUS_NO_MEMORY;
2452 tevent_schedule_immediate(im,
2453 req->sconn->ev_ctx,
2454 smbd_smb2_request_dispatch_immediate,
2455 req);
2456 return NT_STATUS_OK;
2459 if (req->compound_related) {
2460 req->compound_related = false;
2463 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2465 /* Set credit for these operations (zero credits if this
2466 is a final reply for an async operation). */
2467 smb2_calculate_credits(req, req);
2470 * now check if we need to sign the current response
2472 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2473 status = smb2_signing_encrypt_pdu(req->first_key,
2474 conn->protocol,
2475 firsttf,
2476 req->out.vector_count - first_idx);
2477 if (!NT_STATUS_IS_OK(status)) {
2478 return status;
2480 } else if (req->do_signing) {
2481 struct smbXsrv_session *x = req->session;
2482 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2484 status = smb2_signing_sign_pdu(signing_key,
2485 conn->protocol,
2486 outhdr,
2487 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 return status;
2492 if (req->first_key.length > 0) {
2493 data_blob_clear_free(&req->first_key);
2496 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2497 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2498 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2499 /* Dynamic part is NULL. Chop it off,
2500 We're going to send it via sendfile. */
2501 req->out.vector_count -= 1;
2505 * We're done with this request -
2506 * move it off the "being processed" queue.
2508 DLIST_REMOVE(req->sconn->smb2.requests, req);
2510 req->queue_entry.mem_ctx = req;
2511 req->queue_entry.vector = req->out.vector;
2512 req->queue_entry.count = req->out.vector_count;
2513 DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2514 req->sconn->smb2.send_queue_len++;
2516 status = smbd_smb2_flush_send_queue(sconn);
2517 if (!NT_STATUS_IS_OK(status)) {
2518 return status;
2521 return NT_STATUS_OK;
2524 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2526 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2527 struct tevent_immediate *im,
2528 void *private_data)
2530 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2531 struct smbd_smb2_request);
2532 struct smbd_server_connection *sconn = req->sconn;
2533 NTSTATUS status;
2535 TALLOC_FREE(im);
2537 if (DEBUGLEVEL >= 10) {
2538 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2539 req->current_idx, req->in.vector_count));
2540 print_req_vectors(req);
2543 status = smbd_smb2_request_dispatch(req);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 smbd_server_connection_terminate(sconn, nt_errstr(status));
2546 return;
2549 status = smbd_smb2_request_next_incoming(sconn);
2550 if (!NT_STATUS_IS_OK(status)) {
2551 smbd_server_connection_terminate(sconn, nt_errstr(status));
2552 return;
2556 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2557 NTSTATUS status,
2558 DATA_BLOB body, DATA_BLOB *dyn,
2559 const char *location)
2561 uint8_t *outhdr;
2562 struct iovec *outbody_v;
2563 struct iovec *outdyn_v;
2564 uint32_t next_command_ofs;
2566 DEBUG(10,("smbd_smb2_request_done_ex: "
2567 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2568 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2569 dyn ? "yes": "no",
2570 (unsigned int)(dyn ? dyn->length : 0),
2571 location));
2573 if (body.length < 2) {
2574 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2577 if ((body.length % 2) != 0) {
2578 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2581 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2582 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2583 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2585 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2586 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2588 outbody_v->iov_base = (void *)body.data;
2589 outbody_v->iov_len = body.length;
2591 if (dyn) {
2592 outdyn_v->iov_base = (void *)dyn->data;
2593 outdyn_v->iov_len = dyn->length;
2594 } else {
2595 outdyn_v->iov_base = NULL;
2596 outdyn_v->iov_len = 0;
2599 /* see if we need to recalculate the offset to the next response */
2600 if (next_command_ofs > 0) {
2601 next_command_ofs = SMB2_HDR_BODY;
2602 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2603 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2606 if ((next_command_ofs % 8) != 0) {
2607 size_t pad_size = 8 - (next_command_ofs % 8);
2608 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2610 * if the dyn buffer is empty
2611 * we can use it to add padding
2613 uint8_t *pad;
2615 pad = talloc_zero_array(req,
2616 uint8_t, pad_size);
2617 if (pad == NULL) {
2618 return smbd_smb2_request_error(req,
2619 NT_STATUS_NO_MEMORY);
2622 outdyn_v->iov_base = (void *)pad;
2623 outdyn_v->iov_len = pad_size;
2624 } else {
2626 * For now we copy the dynamic buffer
2627 * and add the padding to the new buffer
2629 size_t old_size;
2630 uint8_t *old_dyn;
2631 size_t new_size;
2632 uint8_t *new_dyn;
2634 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2635 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2637 new_size = old_size + pad_size;
2638 new_dyn = talloc_zero_array(req,
2639 uint8_t, new_size);
2640 if (new_dyn == NULL) {
2641 return smbd_smb2_request_error(req,
2642 NT_STATUS_NO_MEMORY);
2645 memcpy(new_dyn, old_dyn, old_size);
2646 memset(new_dyn + old_size, 0, pad_size);
2648 outdyn_v->iov_base = (void *)new_dyn;
2649 outdyn_v->iov_len = new_size;
2651 next_command_ofs += pad_size;
2654 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2656 return smbd_smb2_request_reply(req);
2659 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2660 NTSTATUS status,
2661 DATA_BLOB *info,
2662 const char *location)
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(req->sconn->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_oplock_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 buf[SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x18];
2728 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2731 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2732 struct smbXsrv_session *session,
2733 struct smbXsrv_tcon *tcon,
2734 struct smbXsrv_open *op,
2735 uint8_t oplock_level)
2737 struct smbd_smb2_send_oplock_break_state *state;
2738 struct smbXsrv_connection *conn = sconn->conn;
2739 uint8_t *tf;
2740 size_t tf_len;
2741 uint8_t *hdr;
2742 uint8_t *body;
2743 size_t body_len;
2744 uint8_t *dyn;
2745 size_t dyn_len;
2746 bool do_encryption = session->global->encryption_required;
2747 uint64_t nonce_high = 0;
2748 uint64_t nonce_low = 0;
2749 NTSTATUS status;
2751 if (tcon->global->encryption_required) {
2752 do_encryption = true;
2755 state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state);
2756 if (state == NULL) {
2757 return NT_STATUS_NO_MEMORY;
2759 state->sconn = sconn;
2761 tf = state->buf;
2762 tf_len = SMB2_TF_HDR_SIZE;
2763 hdr = tf + tf_len;
2764 body = hdr + SMB2_HDR_BODY;
2765 body_len = 0x18;
2766 dyn = body + body_len;
2767 dyn_len = 0;
2769 if (do_encryption) {
2770 nonce_high = session->nonce_high;
2771 nonce_low = session->nonce_low;
2773 session->nonce_low += 1;
2774 if (session->nonce_low == 0) {
2775 session->nonce_low += 1;
2776 session->nonce_high += 1;
2780 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2781 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2782 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2783 SBVAL(tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2785 SIVAL(hdr, 0, SMB2_MAGIC);
2786 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2787 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2788 SIVAL(hdr, SMB2_HDR_STATUS, 0);
2789 SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2790 SSVAL(hdr, SMB2_HDR_CREDIT, 0);
2791 SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2792 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2793 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2794 SIVAL(hdr, SMB2_HDR_PID, 0);
2795 SIVAL(hdr, SMB2_HDR_TID, 0);
2796 SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
2797 memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
2799 SSVAL(body, 0x00, body_len);
2801 SCVAL(body, 0x02, oplock_level);
2802 SCVAL(body, 0x03, 0); /* reserved */
2803 SIVAL(body, 0x04, 0); /* reserved */
2804 SBVAL(body, 0x08, op->global->open_persistent_id);
2805 SBVAL(body, 0x10, op->global->open_volatile_id);
2807 state->vector[0] = (struct iovec) {
2808 .iov_base = state->nbt_hdr,
2809 .iov_len = sizeof(state->nbt_hdr)
2812 if (do_encryption) {
2813 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2814 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
2815 } else {
2816 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2817 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2820 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2821 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2823 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2824 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = body_len;
2826 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2827 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_len;
2829 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2831 if (do_encryption) {
2832 DATA_BLOB encryption_key = session->global->encryption_key;
2834 status = smb2_signing_encrypt_pdu(encryption_key,
2835 conn->protocol,
2836 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2837 SMBD_SMB2_NUM_IOV_PER_REQ);
2838 if (!NT_STATUS_IS_OK(status)) {
2839 return status;
2843 state->queue_entry.mem_ctx = state;
2844 state->queue_entry.vector = state->vector;
2845 state->queue_entry.count = ARRAY_SIZE(state->vector);
2846 DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2847 state->sconn->smb2.send_queue_len++;
2849 status = smbd_smb2_flush_send_queue(sconn);
2850 if (!NT_STATUS_IS_OK(status)) {
2851 return status;
2854 return NT_STATUS_OK;
2857 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2859 NTSTATUS status;
2860 uint32_t flags;
2861 uint64_t file_id_persistent;
2862 uint64_t file_id_volatile;
2863 struct smbXsrv_open *op = NULL;
2864 struct files_struct *fsp = NULL;
2865 const uint8_t *body = NULL;
2868 * This is only called with a pktbuf
2869 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2870 * bytes
2873 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2874 /* Transform header. Cannot recvfile. */
2875 return false;
2877 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2878 /* Not SMB2. Normal error path will cope. */
2879 return false;
2881 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2882 /* Not SMB2. Normal error path will cope. */
2883 return false;
2885 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2886 /* Needs to be a WRITE. */
2887 return false;
2889 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2890 /* Chained. Cannot recvfile. */
2891 return false;
2893 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2894 if (flags & SMB2_HDR_FLAG_CHAINED) {
2895 /* Chained. Cannot recvfile. */
2896 return false;
2898 if (flags & SMB2_HDR_FLAG_SIGNED) {
2899 /* Signed. Cannot recvfile. */
2900 return false;
2903 body = &state->pktbuf[SMB2_HDR_BODY];
2905 file_id_persistent = BVAL(body, 0x10);
2906 file_id_volatile = BVAL(body, 0x18);
2908 status = smb2srv_open_lookup(state->req->sconn->conn,
2909 file_id_persistent,
2910 file_id_volatile,
2911 0, /* now */
2912 &op);
2913 if (!NT_STATUS_IS_OK(status)) {
2914 return false;
2917 fsp = op->compat;
2918 if (fsp == NULL) {
2919 return false;
2921 if (fsp->conn == NULL) {
2922 return false;
2925 if (IS_IPC(fsp->conn)) {
2926 return false;
2928 if (IS_PRINT(fsp->conn)) {
2929 return false;
2932 DEBUG(10,("Doing recvfile write len = %u\n",
2933 (unsigned int)(state->pktfull - state->pktlen)));
2935 return true;
2938 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2940 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2941 size_t max_send_queue_len;
2942 size_t cur_send_queue_len;
2944 if (!NT_STATUS_IS_OK(sconn->status)) {
2946 * we're not supposed to do any io
2948 return NT_STATUS_OK;
2951 if (state->req != NULL) {
2953 * if there is already a tstream_readv_pdu
2954 * pending, we are done.
2956 return NT_STATUS_OK;
2959 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2960 cur_send_queue_len = sconn->smb2.send_queue_len;
2962 if (cur_send_queue_len > max_send_queue_len) {
2964 * if we have a lot of requests to send,
2965 * we wait until they are on the wire until we
2966 * ask for the next request.
2968 return NT_STATUS_OK;
2971 /* ask for the next request */
2972 ZERO_STRUCTP(state);
2973 state->req = smbd_smb2_request_allocate(sconn);
2974 if (state->req == NULL) {
2975 return NT_STATUS_NO_MEMORY;
2977 state->req->sconn = sconn;
2978 state->min_recv_size = lp_min_receive_file_size();
2980 TEVENT_FD_READABLE(sconn->smb2.fde);
2982 return NT_STATUS_OK;
2985 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
2986 uint8_t *inbuf, size_t size)
2988 NTSTATUS status;
2989 struct smbd_smb2_request *req = NULL;
2991 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
2992 (unsigned int)size));
2994 status = smbd_initialize_smb2(sconn);
2995 if (!NT_STATUS_IS_OK(status)) {
2996 smbd_server_connection_terminate(sconn, nt_errstr(status));
2997 return;
3000 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 smbd_server_connection_terminate(sconn, nt_errstr(status));
3003 return;
3006 status = smbd_smb2_request_validate(req);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 smbd_server_connection_terminate(sconn, nt_errstr(status));
3009 return;
3012 status = smbd_smb2_request_setup_out(req);
3013 if (!NT_STATUS_IS_OK(status)) {
3014 smbd_server_connection_terminate(sconn, nt_errstr(status));
3015 return;
3018 status = smbd_smb2_request_dispatch(req);
3019 if (!NT_STATUS_IS_OK(status)) {
3020 smbd_server_connection_terminate(sconn, nt_errstr(status));
3021 return;
3024 status = smbd_smb2_request_next_incoming(sconn);
3025 if (!NT_STATUS_IS_OK(status)) {
3026 smbd_server_connection_terminate(sconn, nt_errstr(status));
3027 return;
3030 sconn->num_requests++;
3033 static int socket_error_from_errno(int ret,
3034 int sys_errno,
3035 bool *retry)
3037 *retry = false;
3039 if (ret >= 0) {
3040 return 0;
3043 if (ret != -1) {
3044 return EIO;
3047 if (sys_errno == 0) {
3048 return EIO;
3051 if (sys_errno == EINTR) {
3052 *retry = true;
3053 return sys_errno;
3056 if (sys_errno == EINPROGRESS) {
3057 *retry = true;
3058 return sys_errno;
3061 if (sys_errno == EAGAIN) {
3062 *retry = true;
3063 return sys_errno;
3066 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3067 if (sys_errno == ENOMEM) {
3068 *retry = true;
3069 return sys_errno;
3072 #ifdef EWOULDBLOCK
3073 #if EWOULDBLOCK != EAGAIN
3074 if (sys_errno == EWOULDBLOCK) {
3075 *retry = true;
3076 return sys_errno;
3078 #endif
3079 #endif
3081 return sys_errno;
3084 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3086 int ret;
3087 int err;
3088 bool retry;
3090 if (sconn->smb2.send_queue == NULL) {
3091 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3092 return NT_STATUS_OK;
3095 while (sconn->smb2.send_queue != NULL) {
3096 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3098 if (e->sendfile_header != NULL) {
3099 size_t size = 0;
3100 size_t i = 0;
3101 uint8_t *buf;
3103 for (i=0; i < e->count; i++) {
3104 size += e->vector[i].iov_len;
3107 if (size <= e->sendfile_header->length) {
3108 buf = e->sendfile_header->data;
3109 } else {
3110 buf = talloc_array(e->mem_ctx, uint8_t, size);
3111 if (buf == NULL) {
3112 return NT_STATUS_NO_MEMORY;
3116 size = 0;
3117 for (i=0; i < e->count; i++) {
3118 memcpy(buf+size,
3119 e->vector[i].iov_base,
3120 e->vector[i].iov_len);
3121 size += e->vector[i].iov_len;
3124 e->sendfile_header->data = buf;
3125 e->sendfile_header->length = size;
3126 e->count = 0;
3128 sconn->smb2.send_queue_len--;
3129 DLIST_REMOVE(sconn->smb2.send_queue, e);
3131 * This triggers the sendfile path via
3132 * the destructor.
3134 talloc_free(e->mem_ctx);
3135 continue;
3138 ret = writev(sconn->sock, e->vector, e->count);
3139 if (ret == 0) {
3140 /* propagate end of file */
3141 return NT_STATUS_INTERNAL_ERROR;
3143 err = socket_error_from_errno(ret, errno, &retry);
3144 if (retry) {
3145 /* retry later */
3146 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3147 return NT_STATUS_OK;
3149 if (err != 0) {
3150 return map_nt_error_from_unix_common(err);
3152 while (ret > 0) {
3153 if (ret < e->vector[0].iov_len) {
3154 uint8_t *base;
3155 base = (uint8_t *)e->vector[0].iov_base;
3156 base += ret;
3157 e->vector[0].iov_base = (void *)base;
3158 e->vector[0].iov_len -= ret;
3159 break;
3161 ret -= e->vector[0].iov_len;
3162 e->vector += 1;
3163 e->count -= 1;
3167 * there're maybe some empty vectors at the end
3168 * which we need to skip, otherwise we would get
3169 * ret == 0 from the readv() call and return EPIPE
3171 while (e->count > 0) {
3172 if (e->vector[0].iov_len > 0) {
3173 break;
3175 e->vector += 1;
3176 e->count -= 1;
3179 if (e->count > 0) {
3180 /* we have more to write */
3181 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3182 return NT_STATUS_OK;
3185 sconn->smb2.send_queue_len--;
3186 DLIST_REMOVE(sconn->smb2.send_queue, e);
3187 talloc_free(e->mem_ctx);
3190 return NT_STATUS_OK;
3193 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3194 uint16_t fde_flags)
3196 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3197 struct smbd_smb2_request *req = NULL;
3198 size_t min_recvfile_size = UINT32_MAX;
3199 int ret;
3200 int err;
3201 bool retry;
3202 NTSTATUS status;
3203 NTTIME now;
3205 if (!NT_STATUS_IS_OK(sconn->status)) {
3207 * we're not supposed to do any io
3209 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3210 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3211 return NT_STATUS_OK;
3214 if (fde_flags & TEVENT_FD_WRITE) {
3215 status = smbd_smb2_flush_send_queue(sconn);
3216 if (!NT_STATUS_IS_OK(status)) {
3217 return status;
3221 if (!(fde_flags & TEVENT_FD_READ)) {
3222 return NT_STATUS_OK;
3225 if (state->req == NULL) {
3226 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3227 return NT_STATUS_OK;
3230 again:
3231 if (!state->hdr.done) {
3232 state->hdr.done = true;
3234 state->vector.iov_base = (void *)state->hdr.nbt;
3235 state->vector.iov_len = NBT_HDR_SIZE;
3238 ret = readv(sconn->sock, &state->vector, 1);
3239 if (ret == 0) {
3240 /* propagate end of file */
3241 return NT_STATUS_END_OF_FILE;
3243 err = socket_error_from_errno(ret, errno, &retry);
3244 if (retry) {
3245 /* retry later */
3246 TEVENT_FD_READABLE(sconn->smb2.fde);
3247 return NT_STATUS_OK;
3249 if (err != 0) {
3250 return map_nt_error_from_unix_common(err);
3253 if (ret < state->vector.iov_len) {
3254 uint8_t *base;
3255 base = (uint8_t *)state->vector.iov_base;
3256 base += ret;
3257 state->vector.iov_base = (void *)base;
3258 state->vector.iov_len -= ret;
3259 /* we have more to read */
3260 TEVENT_FD_READABLE(sconn->smb2.fde);
3261 return NT_STATUS_OK;
3264 if (state->pktlen > 0) {
3265 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3267 * Not a possible receivefile write.
3268 * Read the rest of the data.
3270 state->doing_receivefile = false;
3272 state->pktbuf = talloc_realloc(state->req,
3273 state->pktbuf,
3274 uint8_t,
3275 state->pktfull);
3276 if (state->pktbuf == NULL) {
3277 return NT_STATUS_NO_MEMORY;
3280 state->vector.iov_base = (void *)(state->pktbuf +
3281 state->pktlen);
3282 state->vector.iov_len = (state->pktfull -
3283 state->pktlen);
3285 state->pktlen = state->pktfull;
3286 goto again;
3290 * Either this is a receivefile write so we've
3291 * done a short read, or if not we have all the data.
3293 goto got_full;
3297 * Now we analyze the NBT header
3299 if (state->hdr.nbt[0] != 0x00) {
3300 state->min_recv_size = 0;
3302 state->pktfull = smb2_len(state->hdr.nbt);
3303 if (state->pktfull == 0) {
3304 goto got_full;
3307 if (state->min_recv_size != 0) {
3308 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3309 min_recvfile_size += state->min_recv_size;
3312 if (state->pktfull > min_recvfile_size) {
3314 * Might be a receivefile write. Read the SMB2 HEADER +
3315 * SMB2_WRITE header first. Set 'doing_receivefile'
3316 * as we're *attempting* receivefile write. If this
3317 * turns out not to be a SMB2_WRITE request or otherwise
3318 * not suitable then we'll just read the rest of the data
3319 * the next time this function is called.
3321 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3322 state->doing_receivefile = true;
3323 } else {
3324 state->pktlen = state->pktfull;
3327 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3328 if (state->pktbuf == NULL) {
3329 return NT_STATUS_NO_MEMORY;
3332 state->vector.iov_base = (void *)state->pktbuf;
3333 state->vector.iov_len = state->pktlen;
3335 goto again;
3337 got_full:
3339 if (state->hdr.nbt[0] != 0x00) {
3340 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3341 state->hdr.nbt[0]));
3343 req = state->req;
3344 ZERO_STRUCTP(state);
3345 state->req = req;
3346 state->min_recv_size = lp_min_receive_file_size();
3347 req = NULL;
3348 goto again;
3351 req = state->req;
3352 state->req = NULL;
3354 req->request_time = timeval_current();
3355 now = timeval_to_nttime(&req->request_time);
3357 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3358 now,
3359 state->pktbuf,
3360 state->pktlen,
3361 req,
3362 &req->in.vector,
3363 &req->in.vector_count);
3364 if (!NT_STATUS_IS_OK(status)) {
3365 return status;
3368 if (state->doing_receivefile) {
3369 req->smb1req = talloc_zero(req, struct smb_request);
3370 if (req->smb1req == NULL) {
3371 return NT_STATUS_NO_MEMORY;
3373 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3376 ZERO_STRUCTP(state);
3378 req->current_idx = 1;
3380 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3381 req->current_idx, req->in.vector_count));
3383 status = smbd_smb2_request_validate(req);
3384 if (!NT_STATUS_IS_OK(status)) {
3385 return status;
3388 status = smbd_smb2_request_setup_out(req);
3389 if (!NT_STATUS_IS_OK(status)) {
3390 return status;
3393 status = smbd_smb2_request_dispatch(req);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 return status;
3398 sconn->num_requests++;
3400 /* The timeout_processing function isn't run nearly
3401 often enough to implement 'max log size' without
3402 overrunning the size of the file by many megabytes.
3403 This is especially true if we are running at debug
3404 level 10. Checking every 50 SMB2s is a nice
3405 tradeoff of performance vs log file size overrun. */
3407 if ((sconn->num_requests % 50) == 0 &&
3408 need_to_check_log_size()) {
3409 change_to_root_user();
3410 check_log_size();
3413 status = smbd_smb2_request_next_incoming(sconn);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 return status;
3418 return NT_STATUS_OK;
3421 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3422 struct tevent_fd *fde,
3423 uint16_t flags,
3424 void *private_data)
3426 struct smbd_server_connection *sconn =
3427 talloc_get_type_abort(private_data,
3428 struct smbd_server_connection);
3429 NTSTATUS status;
3431 status = smbd_smb2_io_handler(sconn, flags);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 smbd_server_connection_terminate(sconn, nt_errstr(status));
3434 return;