s3:smb2_server: pass smbXsrv_connection to smbd_smb2_request_next_incoming()
[Samba.git] / source3 / smbd / smb2_server.c
blobc7506cb5477b2913bde55d8f92c64b99e35052e2
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
35 uint16_t flags,
36 void *private_data);
37 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
39 static const struct smbd_smb2_dispatch_table {
40 uint16_t opcode;
41 const char *name;
42 bool need_session;
43 bool need_tcon;
44 bool as_root;
45 uint16_t fileid_ofs;
46 bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
50 _OP(SMB2_OP_NEGPROT),
51 .as_root = true,
52 },{
53 _OP(SMB2_OP_SESSSETUP),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_LOGOFF),
57 .need_session = true,
58 .as_root = true,
59 },{
60 _OP(SMB2_OP_TCON),
61 .need_session = true,
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
69 .as_root = true,
70 },{
71 _OP(SMB2_OP_TDIS),
72 .need_session = true,
73 .need_tcon = true,
74 .as_root = true,
75 },{
76 _OP(SMB2_OP_CREATE),
77 .need_session = true,
78 .need_tcon = true,
79 },{
80 _OP(SMB2_OP_CLOSE),
81 .need_session = true,
82 .need_tcon = true,
83 .fileid_ofs = 0x08,
84 },{
85 _OP(SMB2_OP_FLUSH),
86 .need_session = true,
87 .need_tcon = true,
88 .fileid_ofs = 0x08,
89 },{
90 _OP(SMB2_OP_READ),
91 .need_session = true,
92 .need_tcon = true,
93 .fileid_ofs = 0x10,
94 },{
95 _OP(SMB2_OP_WRITE),
96 .need_session = true,
97 .need_tcon = true,
98 .fileid_ofs = 0x10,
99 },{
100 _OP(SMB2_OP_LOCK),
101 .need_session = true,
102 .need_tcon = true,
103 .fileid_ofs = 0x08,
105 _OP(SMB2_OP_IOCTL),
106 .need_session = true,
107 .need_tcon = true,
108 .fileid_ofs = 0x08,
109 .allow_invalid_fileid = true,
111 _OP(SMB2_OP_CANCEL),
112 .as_root = true,
114 _OP(SMB2_OP_KEEPALIVE),
115 .as_root = true,
117 _OP(SMB2_OP_FIND),
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x08,
122 _OP(SMB2_OP_NOTIFY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_GETINFO),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x18,
132 _OP(SMB2_OP_SETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x10,
137 _OP(SMB2_OP_BREAK),
138 .need_session = true,
139 .need_tcon = true,
141 * we do not set
142 * .fileid_ofs here
143 * as LEASE breaks does not
144 * have a file id
149 const char *smb2_opcode_name(uint16_t opcode)
151 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table[opcode].name;
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 const struct smbd_smb2_dispatch_table *ret = NULL;
161 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
162 return NULL;
165 ret = &smbd_smb2_table[opcode];
167 SMB_ASSERT(ret->opcode == opcode);
169 return ret;
172 static void print_req_vectors(const struct smbd_smb2_request *req)
174 int i;
176 for (i = 0; i < req->in.vector_count; i++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
178 (unsigned int)i,
179 (unsigned int)req->in.vector[i].iov_len);
181 for (i = 0; i < req->out.vector_count; i++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
183 (unsigned int)i,
184 (unsigned int)req->out.vector[i].iov_len);
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 if (size < (4 + SMB2_HDR_BODY)) {
191 return false;
194 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
195 return false;
198 return true;
201 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
203 TALLOC_FREE(xconn->transport.fde);
205 xconn->smb2.credits.seq_low = 0;
206 xconn->smb2.credits.seq_range = 1;
207 xconn->smb2.credits.granted = 1;
208 xconn->smb2.credits.max = lp_smb2_max_credits();
209 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
210 xconn->smb2.credits.max);
211 if (xconn->smb2.credits.bitmap == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
216 xconn,
217 xconn->transport.sock,
218 TEVENT_FD_READ,
219 smbd_smb2_connection_handler,
220 xconn);
221 if (xconn->transport.fde == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* Ensure child is set to non-blocking mode */
226 set_blocking(xconn->transport.sock, false);
227 return NT_STATUS_OK;
230 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
231 #define _smb2_setlen(_buf,len) do { \
232 uint8_t *buf = (uint8_t *)_buf; \
233 buf[0] = 0; \
234 buf[1] = ((len)&0xFF0000)>>16; \
235 buf[2] = ((len)&0xFF00)>>8; \
236 buf[3] = (len)&0xFF; \
237 } while (0)
239 static void smb2_setup_nbt_length(struct iovec *vector, int count)
241 size_t len = 0;
242 int i;
244 for (i=1; i < count; i++) {
245 len += vector[i].iov_len;
248 _smb2_setlen(vector[0].iov_base, len);
251 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
253 if (req->first_key.length > 0) {
254 data_blob_clear_free(&req->first_key);
256 if (req->last_key.length > 0) {
257 data_blob_clear_free(&req->last_key);
259 return 0;
262 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
264 TALLOC_CTX *mem_pool;
265 struct smbd_smb2_request *req;
267 #if 0
268 /* Enable this to find subtle valgrind errors. */
269 mem_pool = talloc_init("smbd_smb2_request_allocate");
270 #else
271 mem_pool = talloc_tos();
272 #endif
273 if (mem_pool == NULL) {
274 return NULL;
277 req = talloc_zero(mem_pool, struct smbd_smb2_request);
278 if (req == NULL) {
279 talloc_free(mem_pool);
280 return NULL;
282 talloc_reparent(mem_pool, mem_ctx, req);
283 #if 0
284 TALLOC_FREE(mem_pool);
285 #endif
287 req->last_session_id = UINT64_MAX;
288 req->last_tid = UINT32_MAX;
290 talloc_set_destructor(req, smbd_smb2_request_destructor);
292 return req;
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
296 NTTIME now,
297 uint8_t *buf,
298 size_t buflen,
299 struct smbd_smb2_request *req,
300 struct iovec **piov,
301 int *pnum_iov)
303 TALLOC_CTX *mem_ctx = req;
304 struct iovec *iov;
305 int num_iov = 1;
306 size_t taken = 0;
307 uint8_t *first_hdr = buf;
308 size_t verified_buflen = 0;
309 uint8_t *tf = NULL;
310 size_t tf_len = 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov = req->in._vector;
317 while (taken < buflen) {
318 size_t len = buflen - taken;
319 uint8_t *hdr = first_hdr + taken;
320 struct iovec *cur;
321 size_t full_size;
322 size_t next_command_ofs;
323 uint16_t body_size;
324 uint8_t *body = NULL;
325 uint32_t dyn_size;
326 uint8_t *dyn = NULL;
327 struct iovec *iov_alloc = NULL;
329 if (iov != req->in._vector) {
330 iov_alloc = iov;
333 if (verified_buflen > taken) {
334 len = verified_buflen - taken;
335 } else {
336 tf = NULL;
337 tf_len = 0;
340 if (len < 4) {
341 DEBUG(10, ("%d bytes left, expected at least %d\n",
342 (int)len, 4));
343 goto inval;
345 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
346 struct smbXsrv_session *s = NULL;
347 uint64_t uid;
348 struct iovec tf_iov[2];
349 NTSTATUS status;
350 size_t enc_len;
352 if (xconn->protocol < PROTOCOL_SMB2_24) {
353 DEBUG(10, ("Got SMB2_TRANSFORM header, "
354 "but dialect[0x%04X] is used\n",
355 xconn->smb2.server.dialect));
356 goto inval;
359 if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but not negotiated "
362 "client[0x%08X] server[0x%08X]\n",
363 xconn->smb2.client.capabilities,
364 xconn->smb2.server.capabilities));
365 goto inval;
368 if (len < SMB2_TF_HDR_SIZE) {
369 DEBUG(1, ("%d bytes left, expected at least %d\n",
370 (int)len, SMB2_TF_HDR_SIZE));
371 goto inval;
373 tf = hdr;
374 tf_len = SMB2_TF_HDR_SIZE;
375 taken += tf_len;
377 hdr = first_hdr + taken;
378 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
379 uid = BVAL(tf, SMB2_TF_SESSION_ID);
381 if (len < SMB2_TF_HDR_SIZE + enc_len) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)len,
384 (int)(SMB2_TF_HDR_SIZE + enc_len)));
385 goto inval;
388 status = smb2srv_session_lookup(xconn, uid, now, &s);
389 if (s == NULL) {
390 DEBUG(1, ("invalid session[%llu] in "
391 "SMB2_TRANSFORM header\n",
392 (unsigned long long)uid));
393 TALLOC_FREE(iov_alloc);
394 return NT_STATUS_USER_SESSION_DELETED;
397 tf_iov[0].iov_base = (void *)tf;
398 tf_iov[0].iov_len = tf_len;
399 tf_iov[1].iov_base = (void *)hdr;
400 tf_iov[1].iov_len = enc_len;
402 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
403 xconn->protocol,
404 tf_iov, 2);
405 if (!NT_STATUS_IS_OK(status)) {
406 TALLOC_FREE(iov_alloc);
407 return status;
410 verified_buflen = taken + enc_len;
411 len = enc_len;
415 * We need the header plus the body length field
418 if (len < SMB2_HDR_BODY + 2) {
419 DEBUG(10, ("%d bytes left, expected at least %d\n",
420 (int)len, SMB2_HDR_BODY));
421 goto inval;
423 if (IVAL(hdr, 0) != SMB2_MAGIC) {
424 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
425 IVAL(hdr, 0)));
426 goto inval;
428 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
429 DEBUG(10, ("Got HDR len %d, expected %d\n",
430 SVAL(hdr, 4), SMB2_HDR_BODY));
431 goto inval;
434 full_size = len;
435 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
436 body_size = SVAL(hdr, SMB2_HDR_BODY);
438 if (next_command_ofs != 0) {
439 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
440 goto inval;
442 if (next_command_ofs > full_size) {
443 goto inval;
445 full_size = next_command_ofs;
447 if (body_size < 2) {
448 goto inval;
450 body_size &= 0xfffe;
452 if (body_size > (full_size - SMB2_HDR_BODY)) {
454 * let the caller handle the error
456 body_size = full_size - SMB2_HDR_BODY;
458 body = hdr + SMB2_HDR_BODY;
459 dyn = body + body_size;
460 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
462 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
463 struct iovec *iov_tmp = NULL;
465 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
466 struct iovec,
467 num_iov +
468 SMBD_SMB2_NUM_IOV_PER_REQ);
469 if (iov_tmp == NULL) {
470 TALLOC_FREE(iov_alloc);
471 return NT_STATUS_NO_MEMORY;
474 if (iov_alloc == NULL) {
475 memcpy(iov_tmp,
476 req->in._vector,
477 sizeof(req->in._vector));
480 iov = iov_tmp;
482 cur = &iov[num_iov];
483 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
485 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
486 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
487 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
488 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
489 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
490 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
491 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
492 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
494 taken += full_size;
497 *piov = iov;
498 *pnum_iov = num_iov;
499 return NT_STATUS_OK;
501 inval:
502 if (iov != req->in._vector) {
503 TALLOC_FREE(iov);
505 return NT_STATUS_INVALID_PARAMETER;
508 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
509 uint8_t *inbuf, size_t size,
510 struct smbd_smb2_request **_req)
512 struct smbd_server_connection *sconn = xconn->sconn;
513 struct smbd_smb2_request *req;
514 uint32_t protocol_version;
515 const uint8_t *inhdr = NULL;
516 uint16_t cmd;
517 uint32_t next_command_ofs;
518 NTSTATUS status;
519 NTTIME now;
521 if (size < (4 + SMB2_HDR_BODY + 2)) {
522 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
523 return NT_STATUS_INVALID_PARAMETER;
526 inhdr = inbuf + 4;
528 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
529 if (protocol_version != SMB2_MAGIC) {
530 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
531 protocol_version));
532 return NT_STATUS_INVALID_PARAMETER;
535 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
536 if (cmd != SMB2_OP_NEGPROT) {
537 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
538 cmd));
539 return NT_STATUS_INVALID_PARAMETER;
542 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
543 if (next_command_ofs != 0) {
544 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
545 next_command_ofs));
546 return NT_STATUS_INVALID_PARAMETER;
549 req = smbd_smb2_request_allocate(xconn);
550 if (req == NULL) {
551 return NT_STATUS_NO_MEMORY;
553 req->sconn = sconn;
554 req->xconn = xconn;
556 talloc_steal(req, inbuf);
558 req->request_time = timeval_current();
559 now = timeval_to_nttime(&req->request_time);
561 status = smbd_smb2_inbuf_parse_compound(xconn,
562 now,
563 inbuf + NBT_HDR_SIZE,
564 size - NBT_HDR_SIZE,
565 req, &req->in.vector,
566 &req->in.vector_count);
567 if (!NT_STATUS_IS_OK(status)) {
568 TALLOC_FREE(req);
569 return status;
572 req->current_idx = 1;
574 *_req = req;
575 return NT_STATUS_OK;
578 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
579 uint64_t message_id, uint64_t seq_id)
581 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
582 unsigned int offset;
583 uint64_t seq_tmp;
585 seq_tmp = xconn->smb2.credits.seq_low;
586 if (seq_id < seq_tmp) {
587 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
588 "%llu (sequence id %llu) "
589 "(granted = %u, low = %llu, range = %u)\n",
590 (unsigned long long)message_id,
591 (unsigned long long)seq_id,
592 (unsigned int)xconn->smb2.credits.granted,
593 (unsigned long long)xconn->smb2.credits.seq_low,
594 (unsigned int)xconn->smb2.credits.seq_range));
595 return false;
598 seq_tmp += xconn->smb2.credits.seq_range;
599 if (seq_id >= seq_tmp) {
600 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
601 "%llu (sequence id %llu) "
602 "(granted = %u, low = %llu, range = %u)\n",
603 (unsigned long long)message_id,
604 (unsigned long long)seq_id,
605 (unsigned int)xconn->smb2.credits.granted,
606 (unsigned long long)xconn->smb2.credits.seq_low,
607 (unsigned int)xconn->smb2.credits.seq_range));
608 return false;
611 offset = seq_id % xconn->smb2.credits.max;
613 if (bitmap_query(credits_bm, offset)) {
614 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
615 "%llu (sequence id %llu) "
616 "(granted = %u, low = %llu, range = %u) "
617 "(bm offset %u)\n",
618 (unsigned long long)message_id,
619 (unsigned long long)seq_id,
620 (unsigned int)xconn->smb2.credits.granted,
621 (unsigned long long)xconn->smb2.credits.seq_low,
622 (unsigned int)xconn->smb2.credits.seq_range,
623 offset));
624 return false;
627 /* Mark the message_ids as seen in the bitmap. */
628 bitmap_set(credits_bm, offset);
630 if (seq_id != xconn->smb2.credits.seq_low) {
631 return true;
635 * Move the window forward by all the message_id's
636 * already seen.
638 while (bitmap_query(credits_bm, offset)) {
639 DEBUG(10,("smb2_validate_sequence_number: clearing "
640 "id %llu (position %u) from bitmap\n",
641 (unsigned long long)(xconn->smb2.credits.seq_low),
642 offset));
643 bitmap_clear(credits_bm, offset);
645 xconn->smb2.credits.seq_low += 1;
646 xconn->smb2.credits.seq_range -= 1;
647 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
650 return true;
653 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
654 const uint8_t *inhdr)
656 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
657 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
658 uint16_t credit_charge = 1;
659 uint64_t i;
661 if (opcode == SMB2_OP_CANCEL) {
662 /* SMB2_CANCEL requests by definition resend messageids. */
663 return true;
666 if (xconn->smb2.credits.multicredit) {
667 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
668 credit_charge = MAX(credit_charge, 1);
671 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
672 "credits_granted %llu, "
673 "seqnum low/range: %llu/%llu\n",
674 (unsigned long long) message_id,
675 (unsigned long long) credit_charge,
676 (unsigned long long) xconn->smb2.credits.granted,
677 (unsigned long long) xconn->smb2.credits.seq_low,
678 (unsigned long long) xconn->smb2.credits.seq_range));
680 if (xconn->smb2.credits.granted < credit_charge) {
681 DEBUG(0, ("smb2_validate_message_id: client used more "
682 "credits than granted, mid %llu, charge %llu, "
683 "credits_granted %llu, "
684 "seqnum low/range: %llu/%llu\n",
685 (unsigned long long) message_id,
686 (unsigned long long) credit_charge,
687 (unsigned long long) xconn->smb2.credits.granted,
688 (unsigned long long) xconn->smb2.credits.seq_low,
689 (unsigned long long) xconn->smb2.credits.seq_range));
690 return false;
694 * now check the message ids
696 * for multi-credit requests we need to check all current mid plus
697 * the implicit mids caused by the credit charge
698 * e.g. current mid = 15, charge 5 => mark 15-19 as used
701 for (i = 0; i <= (credit_charge-1); i++) {
702 uint64_t id = message_id + i;
703 bool ok;
705 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
706 (unsigned long long)message_id,
707 credit_charge,
708 (unsigned long long)id));
710 ok = smb2_validate_sequence_number(xconn, message_id, id);
711 if (!ok) {
712 return false;
716 /* substract used credits */
717 xconn->smb2.credits.granted -= credit_charge;
719 return true;
722 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
724 int count;
725 int idx;
727 count = req->in.vector_count;
729 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
730 /* It's not a SMB2 request */
731 return NT_STATUS_INVALID_PARAMETER;
734 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
735 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
736 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
737 const uint8_t *inhdr = NULL;
739 if (hdr->iov_len != SMB2_HDR_BODY) {
740 return NT_STATUS_INVALID_PARAMETER;
743 if (body->iov_len < 2) {
744 return NT_STATUS_INVALID_PARAMETER;
747 inhdr = (const uint8_t *)hdr->iov_base;
749 /* Check the SMB2 header */
750 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
751 return NT_STATUS_INVALID_PARAMETER;
754 if (!smb2_validate_message_id(req->xconn, inhdr)) {
755 return NT_STATUS_INVALID_PARAMETER;
759 return NT_STATUS_OK;
762 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
763 const struct iovec *in_vector,
764 struct iovec *out_vector)
766 struct smbd_server_connection *sconn = xconn->sconn;
767 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
768 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
769 uint16_t credit_charge = 1;
770 uint16_t credits_requested;
771 uint32_t out_flags;
772 uint16_t cmd;
773 NTSTATUS out_status;
774 uint16_t credits_granted = 0;
775 uint64_t credits_possible;
776 uint16_t current_max_credits;
779 * first we grant only 1/16th of the max range.
781 * Windows also starts with the 1/16th and then grants
782 * more later. I was only able to trigger higher
783 * values, when using a very high credit charge.
785 * TODO: scale up depending on load, free memory
786 * or other stuff.
787 * Maybe also on the relationship between number
788 * of requests and the used sequence number.
789 * Which means we would grant more credits
790 * for client which use multi credit requests.
792 current_max_credits = xconn->smb2.credits.max / 16;
793 current_max_credits = MAX(current_max_credits, 1);
795 if (xconn->smb2.credits.multicredit) {
796 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
797 credit_charge = MAX(credit_charge, 1);
800 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
801 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
802 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
803 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
805 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
807 if (xconn->smb2.credits.max < credit_charge) {
808 smbd_server_connection_terminate(sconn,
809 "client error: credit charge > max credits\n");
810 return;
813 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
815 * In case we already send an async interim
816 * response, we should not grant
817 * credits on the final response.
819 credits_granted = 0;
820 } else if (credits_requested > 0) {
821 uint16_t additional_max = 0;
822 uint16_t additional_credits = credits_requested - 1;
824 switch (cmd) {
825 case SMB2_OP_NEGPROT:
826 break;
827 case SMB2_OP_SESSSETUP:
829 * Windows 2012 RC1 starts to grant
830 * additional credits
831 * with a successful session setup
833 if (NT_STATUS_IS_OK(out_status)) {
834 additional_max = 32;
836 break;
837 default:
839 * We match windows and only grant additional credits
840 * in chunks of 32.
842 additional_max = 32;
843 break;
846 additional_credits = MIN(additional_credits, additional_max);
848 credits_granted = credit_charge + additional_credits;
849 } else if (xconn->smb2.credits.granted == 0) {
851 * Make sure the client has always at least one credit
853 credits_granted = 1;
857 * sequence numbers should not wrap
859 * 1. calculate the possible credits until
860 * the sequence numbers start to wrap on 64-bit.
862 * 2. UINT64_MAX is used for Break Notifications.
864 * 2. truncate the possible credits to the maximum
865 * credits we want to grant to the client in total.
867 * 3. remove the range we'll already granted to the client
868 * this makes sure the client consumes the lowest sequence
869 * number, before we can grant additional credits.
871 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
872 if (credits_possible > 0) {
873 /* remove UINT64_MAX */
874 credits_possible -= 1;
876 credits_possible = MIN(credits_possible, current_max_credits);
877 credits_possible -= xconn->smb2.credits.seq_range;
879 credits_granted = MIN(credits_granted, credits_possible);
881 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
882 xconn->smb2.credits.granted += credits_granted;
883 xconn->smb2.credits.seq_range += credits_granted;
885 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
886 "granted %u, current possible/max %u/%u, "
887 "total granted/max/low/range %u/%u/%llu/%u\n",
888 (unsigned int)credits_requested,
889 (unsigned int)credit_charge,
890 (unsigned int)credits_granted,
891 (unsigned int)credits_possible,
892 (unsigned int)current_max_credits,
893 (unsigned int)xconn->smb2.credits.granted,
894 (unsigned int)xconn->smb2.credits.max,
895 (unsigned long long)xconn->smb2.credits.seq_low,
896 (unsigned int)xconn->smb2.credits.seq_range));
899 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
900 struct smbd_smb2_request *outreq)
902 int count, idx;
903 uint16_t total_credits = 0;
905 count = outreq->out.vector_count;
907 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
908 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
909 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
910 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
912 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
914 /* To match Windows, count up what we
915 just granted. */
916 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
917 /* Set to zero in all but the last reply. */
918 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
919 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
920 } else {
921 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
926 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
928 if (req->current_idx <= 1) {
929 if (size <= sizeof(req->out._body)) {
930 return data_blob_const(req->out._body, size);
934 return data_blob_talloc(req, NULL, size);
937 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
939 struct smbXsrv_connection *xconn = req->sconn->conn;
940 TALLOC_CTX *mem_ctx;
941 struct iovec *vector;
942 int count;
943 int idx;
945 count = req->in.vector_count;
946 if (count <= ARRAY_SIZE(req->out._vector)) {
947 mem_ctx = req;
948 vector = req->out._vector;
949 } else {
950 vector = talloc_zero_array(req, struct iovec, count);
951 if (vector == NULL) {
952 return NT_STATUS_NO_MEMORY;
954 mem_ctx = vector;
957 vector[0].iov_base = req->out.nbt_hdr;
958 vector[0].iov_len = 4;
959 SIVAL(req->out.nbt_hdr, 0, 0);
961 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
962 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
963 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
964 uint8_t *outhdr = NULL;
965 uint8_t *outbody = NULL;
966 uint32_t next_command_ofs = 0;
967 struct iovec *current = &vector[idx];
969 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
970 /* we have a next command -
971 * setup for the error case. */
972 next_command_ofs = SMB2_HDR_BODY + 9;
975 if (idx == 1) {
976 outhdr = req->out._hdr;
977 } else {
978 outhdr = talloc_zero_array(mem_ctx, uint8_t,
979 OUTVEC_ALLOC_SIZE);
980 if (outhdr == NULL) {
981 return NT_STATUS_NO_MEMORY;
985 outbody = outhdr + SMB2_HDR_BODY;
988 * SMBD_SMB2_TF_IOV_OFS might be used later
990 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
991 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
993 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
994 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
996 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
997 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
999 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1000 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1002 /* setup the SMB2 header */
1003 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1004 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1005 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1006 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1007 SIVAL(outhdr, SMB2_HDR_STATUS,
1008 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1009 SSVAL(outhdr, SMB2_HDR_OPCODE,
1010 SVAL(inhdr, SMB2_HDR_OPCODE));
1011 SIVAL(outhdr, SMB2_HDR_FLAGS,
1012 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1013 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1014 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1015 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1016 SIVAL(outhdr, SMB2_HDR_PID,
1017 IVAL(inhdr, SMB2_HDR_PID));
1018 SIVAL(outhdr, SMB2_HDR_TID,
1019 IVAL(inhdr, SMB2_HDR_TID));
1020 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1021 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1022 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1023 inhdr + SMB2_HDR_SIGNATURE, 16);
1025 /* setup error body header */
1026 SSVAL(outbody, 0x00, 0x08 + 1);
1027 SSVAL(outbody, 0x02, 0);
1028 SIVAL(outbody, 0x04, 0);
1031 req->out.vector = vector;
1032 req->out.vector_count = count;
1034 /* setup the length of the NBT packet */
1035 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1037 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1039 return NT_STATUS_OK;
1042 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1043 const char *reason,
1044 const char *location)
1046 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1047 reason, location));
1048 exit_server_cleanly(reason);
1051 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1052 struct iovec *outvec,
1053 const struct iovec *srcvec)
1055 const uint8_t *srctf;
1056 size_t srctf_len;
1057 const uint8_t *srchdr;
1058 size_t srchdr_len;
1059 const uint8_t *srcbody;
1060 size_t srcbody_len;
1061 const uint8_t *expected_srcbody;
1062 const uint8_t *srcdyn;
1063 size_t srcdyn_len;
1064 const uint8_t *expected_srcdyn;
1065 uint8_t *dsttf;
1066 uint8_t *dsthdr;
1067 uint8_t *dstbody;
1068 uint8_t *dstdyn;
1070 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1071 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1072 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1073 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1074 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1075 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1076 expected_srcbody = srchdr + SMB2_HDR_BODY;
1077 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1078 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1079 expected_srcdyn = srcbody + 8;
1081 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1082 return false;
1085 if (srchdr_len != SMB2_HDR_BODY) {
1086 return false;
1089 if (srctf_len == SMB2_TF_HDR_SIZE) {
1090 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1091 if (dsttf == NULL) {
1092 return false;
1094 } else {
1095 dsttf = NULL;
1097 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1098 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1100 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1101 * be allocated with size OUTVEC_ALLOC_SIZE. */
1103 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1104 if (dsthdr == NULL) {
1105 return false;
1107 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1108 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1111 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1112 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1113 * then duplicate this. Else use talloc_memdup().
1116 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1117 dstbody = dsthdr + SMB2_HDR_BODY;
1118 } else {
1119 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1120 if (dstbody == NULL) {
1121 return false;
1124 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1125 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1128 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1129 * pointing to
1130 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1131 * then duplicate this. Else use talloc_memdup().
1134 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1135 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1136 } else if (srcdyn == NULL) {
1137 dstdyn = NULL;
1138 } else {
1139 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1140 if (dstdyn == NULL) {
1141 return false;
1144 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1145 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1147 return true;
1150 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1152 struct smbd_smb2_request *newreq = NULL;
1153 struct iovec *outvec = NULL;
1154 int count = req->out.vector_count;
1155 int i;
1157 newreq = smbd_smb2_request_allocate(req->xconn);
1158 if (!newreq) {
1159 return NULL;
1162 newreq->sconn = req->sconn;
1163 newreq->xconn = req->xconn;
1164 newreq->session = req->session;
1165 newreq->do_encryption = req->do_encryption;
1166 newreq->do_signing = req->do_signing;
1167 newreq->current_idx = req->current_idx;
1169 outvec = talloc_zero_array(newreq, struct iovec, count);
1170 if (!outvec) {
1171 TALLOC_FREE(newreq);
1172 return NULL;
1174 newreq->out.vector = outvec;
1175 newreq->out.vector_count = count;
1177 /* Setup the outvec's identically to req. */
1178 outvec[0].iov_base = newreq->out.nbt_hdr;
1179 outvec[0].iov_len = 4;
1180 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1182 /* Setup the vectors identically to the ones in req. */
1183 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1184 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1185 break;
1189 if (i < count) {
1190 /* Alloc failed. */
1191 TALLOC_FREE(newreq);
1192 return NULL;
1195 smb2_setup_nbt_length(newreq->out.vector,
1196 newreq->out.vector_count);
1198 return newreq;
1201 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1203 struct smbXsrv_connection *xconn = req->xconn;
1204 int first_idx = 1;
1205 struct iovec *firsttf = NULL;
1206 struct iovec *outhdr_v = NULL;
1207 uint8_t *outhdr = NULL;
1208 struct smbd_smb2_request *nreq = NULL;
1209 NTSTATUS status;
1211 /* Create a new smb2 request we'll use
1212 for the interim return. */
1213 nreq = dup_smb2_req(req);
1214 if (!nreq) {
1215 return NT_STATUS_NO_MEMORY;
1218 /* Lose the last X out vectors. They're the
1219 ones we'll be using for the async reply. */
1220 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1222 smb2_setup_nbt_length(nreq->out.vector,
1223 nreq->out.vector_count);
1225 /* Step back to the previous reply. */
1226 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1227 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1228 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1229 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1230 /* And end the chain. */
1231 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1233 /* Calculate outgoing credits */
1234 smb2_calculate_credits(req, nreq);
1236 if (DEBUGLEVEL >= 10) {
1237 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1238 (unsigned int)nreq->current_idx );
1239 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1240 (unsigned int)nreq->out.vector_count );
1241 print_req_vectors(nreq);
1245 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1246 * we need to sign/encrypt here with the last/first key we remembered
1248 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1249 status = smb2_signing_encrypt_pdu(req->first_key,
1250 xconn->protocol,
1251 firsttf,
1252 nreq->out.vector_count - first_idx);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 return status;
1256 } else if (req->last_key.length > 0) {
1257 status = smb2_signing_sign_pdu(req->last_key,
1258 xconn->protocol,
1259 outhdr_v,
1260 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 return status;
1266 nreq->queue_entry.mem_ctx = nreq;
1267 nreq->queue_entry.vector = nreq->out.vector;
1268 nreq->queue_entry.count = nreq->out.vector_count;
1269 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1270 xconn->smb2.send_queue_len++;
1272 status = smbd_smb2_flush_send_queue(xconn);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 return status;
1277 return NT_STATUS_OK;
1280 struct smbd_smb2_request_pending_state {
1281 struct smbd_server_connection *sconn;
1282 struct smbd_smb2_send_queue queue_entry;
1283 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1284 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1287 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1288 struct tevent_timer *te,
1289 struct timeval current_time,
1290 void *private_data);
1292 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1293 struct tevent_req *subreq,
1294 uint32_t defer_time)
1296 NTSTATUS status;
1297 struct timeval defer_endtime;
1298 uint8_t *outhdr = NULL;
1299 uint32_t flags;
1301 if (!tevent_req_is_in_progress(subreq)) {
1303 * This is a performance optimization,
1304 * it avoids one tevent_loop iteration,
1305 * which means we avoid one
1306 * talloc_stackframe_pool/talloc_free pair.
1308 tevent_req_notify_callback(subreq);
1309 return NT_STATUS_OK;
1312 req->subreq = subreq;
1313 subreq = NULL;
1315 if (req->async_te) {
1316 /* We're already async. */
1317 return NT_STATUS_OK;
1320 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1321 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1322 if (flags & SMB2_HDR_FLAG_ASYNC) {
1323 /* We're already async. */
1324 return NT_STATUS_OK;
1327 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1329 * We're trying to go async in a compound
1330 * request chain.
1331 * This is only allowed for opens that
1332 * cause an oplock break, otherwise it
1333 * is not allowed. See [MS-SMB2].pdf
1334 * note <194> on Section 3.3.5.2.7.
1336 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1338 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1340 * Cancel the outstanding request.
1342 bool ok = tevent_req_cancel(req->subreq);
1343 if (ok) {
1344 return NT_STATUS_OK;
1346 TALLOC_FREE(req->subreq);
1347 return smbd_smb2_request_error(req,
1348 NT_STATUS_INTERNAL_ERROR);
1352 if (DEBUGLEVEL >= 10) {
1353 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1354 (unsigned int)req->current_idx );
1355 print_req_vectors(req);
1358 if (req->current_idx > 1) {
1360 * We're going async in a compound
1361 * chain after the first request has
1362 * already been processed. Send an
1363 * interim response containing the
1364 * set of replies already generated.
1366 int idx = req->current_idx;
1368 status = smb2_send_async_interim_response(req);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 return status;
1372 if (req->first_key.length > 0) {
1373 data_blob_clear_free(&req->first_key);
1376 req->current_idx = 1;
1379 * Re-arrange the in.vectors to remove what
1380 * we just sent.
1382 memmove(&req->in.vector[1],
1383 &req->in.vector[idx],
1384 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1385 req->in.vector_count = 1 + (req->in.vector_count - idx);
1387 /* Re-arrange the out.vectors to match. */
1388 memmove(&req->out.vector[1],
1389 &req->out.vector[idx],
1390 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1391 req->out.vector_count = 1 + (req->out.vector_count - idx);
1393 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1395 * We only have one remaining request as
1396 * we've processed everything else.
1397 * This is no longer a compound request.
1399 req->compound_related = false;
1400 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1401 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1402 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1405 if (req->last_key.length > 0) {
1406 data_blob_clear_free(&req->last_key);
1409 defer_endtime = timeval_current_ofs_usec(defer_time);
1410 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1411 req, defer_endtime,
1412 smbd_smb2_request_pending_timer,
1413 req);
1414 if (req->async_te == NULL) {
1415 return NT_STATUS_NO_MEMORY;
1418 return NT_STATUS_OK;
1421 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1422 struct tevent_timer *te,
1423 struct timeval current_time,
1424 void *private_data)
1426 struct smbd_smb2_request *req =
1427 talloc_get_type_abort(private_data,
1428 struct smbd_smb2_request);
1429 struct smbd_server_connection *sconn = req->sconn;
1430 struct smbXsrv_connection *xconn = sconn->conn;
1431 struct smbd_smb2_request_pending_state *state = NULL;
1432 uint8_t *outhdr = NULL;
1433 const uint8_t *inhdr = NULL;
1434 uint8_t *tf = NULL;
1435 size_t tf_len = 0;
1436 uint8_t *hdr = NULL;
1437 uint8_t *body = NULL;
1438 uint8_t *dyn = NULL;
1439 uint32_t flags = 0;
1440 uint64_t session_id = 0;
1441 uint64_t message_id = 0;
1442 uint64_t nonce_high = 0;
1443 uint64_t nonce_low = 0;
1444 uint64_t async_id = 0;
1445 NTSTATUS status;
1447 TALLOC_FREE(req->async_te);
1449 /* Ensure our final reply matches the interim one. */
1450 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1451 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1452 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1453 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1454 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1456 async_id = message_id; /* keep it simple for now... */
1458 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1459 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1461 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1462 "going async\n",
1463 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1464 (unsigned long long)async_id ));
1467 * What we send is identical to a smbd_smb2_request_error
1468 * packet with an error status of STATUS_PENDING. Make use
1469 * of this fact sometime when refactoring. JRA.
1472 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1473 if (state == NULL) {
1474 smbd_server_connection_terminate(req->sconn,
1475 nt_errstr(NT_STATUS_NO_MEMORY));
1476 return;
1478 state->sconn = req->sconn;
1480 tf = state->buf + NBT_HDR_SIZE;
1481 tf_len = SMB2_TF_HDR_SIZE;
1483 hdr = tf + SMB2_TF_HDR_SIZE;
1484 body = hdr + SMB2_HDR_BODY;
1485 dyn = body + 8;
1487 if (req->do_encryption) {
1488 struct smbXsrv_session *x = req->session;
1490 nonce_high = x->nonce_high;
1491 nonce_low = x->nonce_low;
1493 x->nonce_low += 1;
1494 if (x->nonce_low == 0) {
1495 x->nonce_low += 1;
1496 x->nonce_high += 1;
1500 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1501 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1502 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1503 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1505 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1506 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1507 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1508 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1509 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1511 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1512 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1513 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1514 SBVAL(hdr, SMB2_HDR_PID, async_id);
1515 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1516 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1517 memcpy(hdr+SMB2_HDR_SIGNATURE,
1518 outhdr+SMB2_HDR_SIGNATURE, 16);
1520 SSVAL(body, 0x00, 0x08 + 1);
1522 SCVAL(body, 0x02, 0);
1523 SCVAL(body, 0x03, 0);
1524 SIVAL(body, 0x04, 0);
1525 /* Match W2K8R2... */
1526 SCVAL(dyn, 0x00, 0x21);
1528 state->vector[0].iov_base = (void *)state->buf;
1529 state->vector[0].iov_len = NBT_HDR_SIZE;
1531 if (req->do_encryption) {
1532 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1533 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1534 } else {
1535 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1536 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1539 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1540 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1542 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1543 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1545 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1546 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1548 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1550 /* Ensure we correctly go through crediting. Grant
1551 the credits now, and zero credits on the final
1552 response. */
1553 smb2_set_operation_credit(req->xconn,
1554 SMBD_SMB2_IN_HDR_IOV(req),
1555 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1557 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1559 if (DEBUGLVL(10)) {
1560 int i;
1562 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1563 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1564 (unsigned int)i,
1565 (unsigned int)ARRAY_SIZE(state->vector),
1566 (unsigned int)state->vector[i].iov_len);
1570 if (req->do_encryption) {
1571 struct smbXsrv_session *x = req->session;
1572 DATA_BLOB encryption_key = x->global->encryption_key;
1574 status = smb2_signing_encrypt_pdu(encryption_key,
1575 xconn->protocol,
1576 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1577 SMBD_SMB2_NUM_IOV_PER_REQ);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 smbd_server_connection_terminate(req->sconn,
1580 nt_errstr(status));
1581 return;
1583 } else if (req->do_signing) {
1584 struct smbXsrv_session *x = req->session;
1585 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1587 status = smb2_signing_sign_pdu(signing_key,
1588 xconn->protocol,
1589 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1590 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 smbd_server_connection_terminate(req->sconn,
1593 nt_errstr(status));
1594 return;
1598 state->queue_entry.mem_ctx = state;
1599 state->queue_entry.vector = state->vector;
1600 state->queue_entry.count = ARRAY_SIZE(state->vector);
1601 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1602 xconn->smb2.send_queue_len++;
1604 status = smbd_smb2_flush_send_queue(xconn);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 smbd_server_connection_terminate(sconn,
1607 nt_errstr(status));
1608 return;
1612 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1614 struct smbd_server_connection *sconn = req->sconn;
1615 struct smbXsrv_connection *xconn = sconn->conn;
1616 struct smbd_smb2_request *cur;
1617 const uint8_t *inhdr;
1618 uint32_t flags;
1619 uint64_t search_message_id;
1620 uint64_t search_async_id;
1621 uint64_t found_id;
1623 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1625 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1626 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1627 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1630 * we don't need the request anymore
1631 * cancel requests never have a response
1633 DLIST_REMOVE(xconn->smb2.requests, req);
1634 TALLOC_FREE(req);
1636 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1637 const uint8_t *outhdr;
1638 uint64_t message_id;
1639 uint64_t async_id;
1641 if (cur->compound_related) {
1643 * Never cancel anything in a compound request.
1644 * Way too hard to deal with the result.
1646 continue;
1649 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1651 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1652 async_id = BVAL(outhdr, SMB2_HDR_PID);
1654 if (flags & SMB2_HDR_FLAG_ASYNC) {
1655 if (search_async_id == async_id) {
1656 found_id = async_id;
1657 break;
1659 } else {
1660 if (search_message_id == message_id) {
1661 found_id = message_id;
1662 break;
1667 if (cur && cur->subreq) {
1668 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1669 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1670 "cancel opcode[%s] mid %llu\n",
1671 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1672 (unsigned long long)found_id ));
1673 tevent_req_cancel(cur->subreq);
1676 return NT_STATUS_OK;
1679 /*************************************************************
1680 Ensure an incoming tid is a valid one for us to access.
1681 Change to the associated uid credentials and chdir to the
1682 valid tid directory.
1683 *************************************************************/
1685 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1687 const uint8_t *inhdr;
1688 uint32_t in_flags;
1689 uint32_t in_tid;
1690 struct smbXsrv_tcon *tcon;
1691 NTSTATUS status;
1692 NTTIME now = timeval_to_nttime(&req->request_time);
1694 req->tcon = NULL;
1696 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1698 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1699 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1701 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1702 in_tid = req->last_tid;
1705 req->last_tid = 0;
1707 status = smb2srv_tcon_lookup(req->session,
1708 in_tid, now, &tcon);
1709 if (!NT_STATUS_IS_OK(status)) {
1710 return status;
1713 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1714 return NT_STATUS_ACCESS_DENIED;
1717 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1718 if (!set_current_service(tcon->compat, 0, true)) {
1719 return NT_STATUS_ACCESS_DENIED;
1722 req->tcon = tcon;
1723 req->last_tid = in_tid;
1725 return NT_STATUS_OK;
1728 /*************************************************************
1729 Ensure an incoming session_id is a valid one for us to access.
1730 *************************************************************/
1732 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1734 const uint8_t *inhdr;
1735 uint32_t in_flags;
1736 uint16_t in_opcode;
1737 uint64_t in_session_id;
1738 struct smbXsrv_session *session = NULL;
1739 struct auth_session_info *session_info;
1740 NTSTATUS status;
1741 NTTIME now = timeval_to_nttime(&req->request_time);
1743 req->session = NULL;
1744 req->tcon = NULL;
1746 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1748 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1749 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1750 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1752 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1753 in_session_id = req->last_session_id;
1756 req->last_session_id = 0;
1758 /* lookup an existing session */
1759 status = smb2srv_session_lookup(req->sconn->conn,
1760 in_session_id, now,
1761 &session);
1762 if (session) {
1763 req->session = session;
1764 req->last_session_id = in_session_id;
1766 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1767 switch (in_opcode) {
1768 case SMB2_OP_SESSSETUP:
1769 status = NT_STATUS_OK;
1770 break;
1771 default:
1772 break;
1775 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1776 switch (in_opcode) {
1777 case SMB2_OP_TCON:
1778 case SMB2_OP_CREATE:
1779 case SMB2_OP_GETINFO:
1780 case SMB2_OP_SETINFO:
1781 return NT_STATUS_INVALID_HANDLE;
1782 default:
1784 * Notice the check for
1785 * (session_info == NULL)
1786 * below.
1788 status = NT_STATUS_OK;
1789 break;
1792 if (!NT_STATUS_IS_OK(status)) {
1793 return status;
1796 session_info = session->global->auth_session_info;
1797 if (session_info == NULL) {
1798 return NT_STATUS_INVALID_HANDLE;
1801 if (in_session_id != req->sconn->conn->last_session_id) {
1802 req->sconn->conn->last_session_id = in_session_id;
1803 set_current_user_info(session_info->unix_info->sanitized_username,
1804 session_info->unix_info->unix_name,
1805 session_info->info->domain_name);
1808 return NT_STATUS_OK;
1811 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1812 uint32_t data_length)
1814 struct smbXsrv_connection *xconn = req->sconn->conn;
1815 uint16_t needed_charge;
1816 uint16_t credit_charge = 1;
1817 const uint8_t *inhdr;
1819 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1821 if (xconn->smb2.credits.multicredit) {
1822 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1823 credit_charge = MAX(credit_charge, 1);
1826 needed_charge = (data_length - 1)/ 65536 + 1;
1828 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1829 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1830 credit_charge, needed_charge));
1832 if (needed_charge > credit_charge) {
1833 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1834 credit_charge, needed_charge));
1835 return NT_STATUS_INVALID_PARAMETER;
1838 return NT_STATUS_OK;
1841 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1842 size_t expected_body_size)
1844 struct iovec *inhdr_v;
1845 const uint8_t *inhdr;
1846 uint16_t opcode;
1847 const uint8_t *inbody;
1848 size_t body_size;
1849 size_t min_dyn_size = expected_body_size & 0x00000001;
1850 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1853 * The following should be checked already.
1855 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1856 return NT_STATUS_INTERNAL_ERROR;
1858 if (req->current_idx > max_idx) {
1859 return NT_STATUS_INTERNAL_ERROR;
1862 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1863 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1864 return NT_STATUS_INTERNAL_ERROR;
1866 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1867 return NT_STATUS_INTERNAL_ERROR;
1870 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1871 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1873 switch (opcode) {
1874 case SMB2_OP_IOCTL:
1875 case SMB2_OP_GETINFO:
1876 min_dyn_size = 0;
1877 break;
1878 case SMB2_OP_WRITE:
1879 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1880 if (req->smb1req->unread_bytes < min_dyn_size) {
1881 return NT_STATUS_INVALID_PARAMETER;
1884 min_dyn_size = 0;
1886 break;
1890 * Now check the expected body size,
1891 * where the last byte might be in the
1892 * dynamic section..
1894 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1895 return NT_STATUS_INVALID_PARAMETER;
1897 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1898 return NT_STATUS_INVALID_PARAMETER;
1901 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1903 body_size = SVAL(inbody, 0x00);
1904 if (body_size != expected_body_size) {
1905 return NT_STATUS_INVALID_PARAMETER;
1908 return NT_STATUS_OK;
1911 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1913 struct smbXsrv_connection *xconn = req->sconn->conn;
1914 const struct smbd_smb2_dispatch_table *call = NULL;
1915 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1916 const uint8_t *inhdr;
1917 uint16_t opcode;
1918 uint32_t flags;
1919 uint64_t mid;
1920 NTSTATUS status;
1921 NTSTATUS session_status;
1922 uint32_t allowed_flags;
1923 NTSTATUS return_value;
1924 struct smbXsrv_session *x = NULL;
1925 bool signing_required = false;
1926 bool encryption_required = false;
1928 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1930 /* TODO: verify more things */
1932 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1933 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1934 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1935 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1936 smb2_opcode_name(opcode),
1937 (unsigned long long)mid));
1939 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1941 * once the protocol is negotiated
1942 * SMB2_OP_NEGPROT is not allowed anymore
1944 if (opcode == SMB2_OP_NEGPROT) {
1945 /* drop the connection */
1946 return NT_STATUS_INVALID_PARAMETER;
1948 } else {
1950 * if the protocol is not negotiated yet
1951 * only SMB2_OP_NEGPROT is allowed.
1953 if (opcode != SMB2_OP_NEGPROT) {
1954 /* drop the connection */
1955 return NT_STATUS_INVALID_PARAMETER;
1960 * Check if the client provided a valid session id,
1961 * if so smbd_smb2_request_check_session() calls
1962 * set_current_user_info().
1964 * As some command don't require a valid session id
1965 * we defer the check of the session_status
1967 session_status = smbd_smb2_request_check_session(req);
1968 x = req->session;
1969 if (x != NULL) {
1970 signing_required = x->global->signing_required;
1971 encryption_required = x->global->encryption_required;
1973 if (opcode == SMB2_OP_SESSSETUP &&
1974 x->global->channels[0].signing_key.length) {
1975 signing_required = true;
1979 req->do_signing = false;
1980 req->do_encryption = false;
1981 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1982 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1983 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1985 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1986 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1987 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1988 (unsigned long long)x->global->session_wire_id,
1989 (unsigned long long)tf_session_id));
1991 * TODO: windows allows this...
1992 * should we drop the connection?
1994 * For now we just return ACCESS_DENIED
1995 * (Windows clients never trigger this)
1996 * and wait for an update of [MS-SMB2].
1998 return smbd_smb2_request_error(req,
1999 NT_STATUS_ACCESS_DENIED);
2002 req->do_encryption = true;
2005 if (encryption_required && !req->do_encryption) {
2006 return smbd_smb2_request_error(req,
2007 NT_STATUS_ACCESS_DENIED);
2010 call = smbd_smb2_call(opcode);
2011 if (call == NULL) {
2012 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2015 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2016 SMB2_HDR_FLAG_SIGNED |
2017 SMB2_HDR_FLAG_DFS;
2018 if (opcode == SMB2_OP_CANCEL) {
2019 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2021 if ((flags & ~allowed_flags) != 0) {
2022 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2025 if (flags & SMB2_HDR_FLAG_CHAINED) {
2027 * This check is mostly for giving the correct error code
2028 * for compounded requests.
2030 if (!NT_STATUS_IS_OK(session_status)) {
2031 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2033 } else {
2034 req->compat_chain_fsp = NULL;
2037 if (req->do_encryption) {
2038 signing_required = false;
2039 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2040 DATA_BLOB signing_key;
2042 if (x == NULL) {
2044 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2045 * If the SMB2 header of the SMB2 NEGOTIATE
2046 * request has the SMB2_FLAGS_SIGNED bit set in the
2047 * Flags field, the server MUST fail the request
2048 * with STATUS_INVALID_PARAMETER.
2050 * Microsoft test tool checks this.
2053 if ((opcode == SMB2_OP_NEGPROT) &&
2054 (flags & SMB2_HDR_FLAG_SIGNED)) {
2055 status = NT_STATUS_INVALID_PARAMETER;
2056 } else {
2057 status = NT_STATUS_USER_SESSION_DELETED;
2059 return smbd_smb2_request_error(req, status);
2062 signing_key = x->global->channels[0].signing_key;
2065 * If we have a signing key, we should
2066 * sign the response
2068 if (signing_key.length > 0) {
2069 req->do_signing = true;
2072 status = smb2_signing_check_pdu(signing_key,
2073 xconn->protocol,
2074 SMBD_SMB2_IN_HDR_IOV(req),
2075 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 return smbd_smb2_request_error(req, status);
2081 * Now that we know the request was correctly signed
2082 * we have to sign the response too.
2084 req->do_signing = true;
2086 if (!NT_STATUS_IS_OK(session_status)) {
2087 return smbd_smb2_request_error(req, session_status);
2089 } else if (opcode == SMB2_OP_CANCEL) {
2090 /* Cancel requests are allowed to skip the signing */
2091 } else if (signing_required) {
2093 * If signing is required we try to sign
2094 * a possible error response
2096 req->do_signing = true;
2097 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2100 if (flags & SMB2_HDR_FLAG_CHAINED) {
2101 req->compound_related = true;
2104 if (call->need_session) {
2105 if (!NT_STATUS_IS_OK(session_status)) {
2106 return smbd_smb2_request_error(req, session_status);
2110 if (call->need_tcon) {
2111 SMB_ASSERT(call->need_session);
2114 * This call needs to be run as user.
2116 * smbd_smb2_request_check_tcon()
2117 * calls change_to_user() on success.
2119 status = smbd_smb2_request_check_tcon(req);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 return smbd_smb2_request_error(req, status);
2123 if (req->tcon->global->encryption_required) {
2124 encryption_required = true;
2126 if (encryption_required && !req->do_encryption) {
2127 return smbd_smb2_request_error(req,
2128 NT_STATUS_ACCESS_DENIED);
2132 if (call->fileid_ofs != 0) {
2133 size_t needed = call->fileid_ofs + 16;
2134 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2135 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2136 uint64_t file_id_persistent;
2137 uint64_t file_id_volatile;
2138 struct files_struct *fsp;
2140 SMB_ASSERT(call->need_tcon);
2142 if (needed > body_size) {
2143 return smbd_smb2_request_error(req,
2144 NT_STATUS_INVALID_PARAMETER);
2147 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2148 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2150 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2151 if (fsp == NULL) {
2152 if (!call->allow_invalid_fileid) {
2153 return smbd_smb2_request_error(req,
2154 NT_STATUS_FILE_CLOSED);
2157 if (file_id_persistent != UINT64_MAX) {
2158 return smbd_smb2_request_error(req,
2159 NT_STATUS_FILE_CLOSED);
2161 if (file_id_volatile != UINT64_MAX) {
2162 return smbd_smb2_request_error(req,
2163 NT_STATUS_FILE_CLOSED);
2168 if (call->as_root) {
2169 SMB_ASSERT(call->fileid_ofs == 0);
2170 /* This call needs to be run as root */
2171 change_to_root_user();
2172 } else {
2173 SMB_ASSERT(call->need_tcon);
2176 switch (opcode) {
2177 case SMB2_OP_NEGPROT:
2179 START_PROFILE(smb2_negprot);
2180 return_value = smbd_smb2_request_process_negprot(req);
2181 END_PROFILE(smb2_negprot);
2183 break;
2185 case SMB2_OP_SESSSETUP:
2187 START_PROFILE(smb2_sesssetup);
2188 return_value = smbd_smb2_request_process_sesssetup(req);
2189 END_PROFILE(smb2_sesssetup);
2191 break;
2193 case SMB2_OP_LOGOFF:
2195 START_PROFILE(smb2_logoff);
2196 return_value = smbd_smb2_request_process_logoff(req);
2197 END_PROFILE(smb2_logoff);
2199 break;
2201 case SMB2_OP_TCON:
2203 START_PROFILE(smb2_tcon);
2204 return_value = smbd_smb2_request_process_tcon(req);
2205 END_PROFILE(smb2_tcon);
2207 break;
2209 case SMB2_OP_TDIS:
2211 START_PROFILE(smb2_tdis);
2212 return_value = smbd_smb2_request_process_tdis(req);
2213 END_PROFILE(smb2_tdis);
2215 break;
2217 case SMB2_OP_CREATE:
2219 START_PROFILE(smb2_create);
2220 return_value = smbd_smb2_request_process_create(req);
2221 END_PROFILE(smb2_create);
2223 break;
2225 case SMB2_OP_CLOSE:
2227 START_PROFILE(smb2_close);
2228 return_value = smbd_smb2_request_process_close(req);
2229 END_PROFILE(smb2_close);
2231 break;
2233 case SMB2_OP_FLUSH:
2235 START_PROFILE(smb2_flush);
2236 return_value = smbd_smb2_request_process_flush(req);
2237 END_PROFILE(smb2_flush);
2239 break;
2241 case SMB2_OP_READ:
2243 START_PROFILE(smb2_read);
2244 return_value = smbd_smb2_request_process_read(req);
2245 END_PROFILE(smb2_read);
2247 break;
2249 case SMB2_OP_WRITE:
2251 START_PROFILE(smb2_write);
2252 return_value = smbd_smb2_request_process_write(req);
2253 END_PROFILE(smb2_write);
2255 break;
2257 case SMB2_OP_LOCK:
2259 START_PROFILE(smb2_lock);
2260 return_value = smbd_smb2_request_process_lock(req);
2261 END_PROFILE(smb2_lock);
2263 break;
2265 case SMB2_OP_IOCTL:
2267 START_PROFILE(smb2_ioctl);
2268 return_value = smbd_smb2_request_process_ioctl(req);
2269 END_PROFILE(smb2_ioctl);
2271 break;
2273 case SMB2_OP_CANCEL:
2275 START_PROFILE(smb2_cancel);
2276 return_value = smbd_smb2_request_process_cancel(req);
2277 END_PROFILE(smb2_cancel);
2279 break;
2281 case SMB2_OP_KEEPALIVE:
2283 START_PROFILE(smb2_keepalive);
2284 return_value = smbd_smb2_request_process_keepalive(req);
2285 END_PROFILE(smb2_keepalive);
2287 break;
2289 case SMB2_OP_FIND:
2291 START_PROFILE(smb2_find);
2292 return_value = smbd_smb2_request_process_find(req);
2293 END_PROFILE(smb2_find);
2295 break;
2297 case SMB2_OP_NOTIFY:
2299 START_PROFILE(smb2_notify);
2300 return_value = smbd_smb2_request_process_notify(req);
2301 END_PROFILE(smb2_notify);
2303 break;
2305 case SMB2_OP_GETINFO:
2307 START_PROFILE(smb2_getinfo);
2308 return_value = smbd_smb2_request_process_getinfo(req);
2309 END_PROFILE(smb2_getinfo);
2311 break;
2313 case SMB2_OP_SETINFO:
2315 START_PROFILE(smb2_setinfo);
2316 return_value = smbd_smb2_request_process_setinfo(req);
2317 END_PROFILE(smb2_setinfo);
2319 break;
2321 case SMB2_OP_BREAK:
2323 START_PROFILE(smb2_break);
2324 return_value = smbd_smb2_request_process_break(req);
2325 END_PROFILE(smb2_break);
2327 break;
2329 default:
2330 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2331 break;
2333 return return_value;
2336 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2338 struct smbXsrv_connection *xconn = req->xconn;
2339 int first_idx = 1;
2340 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2341 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2342 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2343 NTSTATUS status;
2345 req->subreq = NULL;
2346 TALLOC_FREE(req->async_te);
2348 if (req->do_encryption &&
2349 (firsttf->iov_len == 0) &&
2350 (req->first_key.length == 0) &&
2351 (req->session != NULL) &&
2352 (req->session->global->encryption_key.length != 0))
2354 DATA_BLOB encryption_key = req->session->global->encryption_key;
2355 uint8_t *tf;
2356 uint64_t session_id = req->session->global->session_wire_id;
2357 struct smbXsrv_session *x = req->session;
2358 uint64_t nonce_high;
2359 uint64_t nonce_low;
2361 nonce_high = x->nonce_high;
2362 nonce_low = x->nonce_low;
2364 x->nonce_low += 1;
2365 if (x->nonce_low == 0) {
2366 x->nonce_low += 1;
2367 x->nonce_high += 1;
2371 * We need to place the SMB2_TRANSFORM header before the
2372 * first SMB2 header
2376 * we need to remember the encryption key
2377 * and defer the signing/encryption until
2378 * we are sure that we do not change
2379 * the header again.
2381 req->first_key = data_blob_dup_talloc(req, encryption_key);
2382 if (req->first_key.data == NULL) {
2383 return NT_STATUS_NO_MEMORY;
2386 tf = talloc_zero_array(req, uint8_t,
2387 SMB2_TF_HDR_SIZE);
2388 if (tf == NULL) {
2389 return NT_STATUS_NO_MEMORY;
2392 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2393 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2394 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2395 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2397 firsttf->iov_base = (void *)tf;
2398 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2401 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2402 (req->last_key.length > 0) &&
2403 (firsttf->iov_len == 0))
2405 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2406 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2409 * As we are sure the header of the last request in the
2410 * compound chain will not change, we can to sign here
2411 * with the last signing key we remembered.
2413 status = smb2_signing_sign_pdu(req->last_key,
2414 xconn->protocol,
2415 lasthdr,
2416 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2417 if (!NT_STATUS_IS_OK(status)) {
2418 return status;
2421 if (req->last_key.length > 0) {
2422 data_blob_clear_free(&req->last_key);
2425 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2427 if (req->current_idx < req->out.vector_count) {
2429 * We must process the remaining compound
2430 * SMB2 requests before any new incoming SMB2
2431 * requests. This is because incoming SMB2
2432 * requests may include a cancel for a
2433 * compound request we haven't processed
2434 * yet.
2436 struct tevent_immediate *im = tevent_create_immediate(req);
2437 if (!im) {
2438 return NT_STATUS_NO_MEMORY;
2441 if (req->do_signing && firsttf->iov_len == 0) {
2442 struct smbXsrv_session *x = req->session;
2443 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2446 * we need to remember the signing key
2447 * and defer the signing until
2448 * we are sure that we do not change
2449 * the header again.
2451 req->last_key = data_blob_dup_talloc(req, signing_key);
2452 if (req->last_key.data == NULL) {
2453 return NT_STATUS_NO_MEMORY;
2457 tevent_schedule_immediate(im,
2458 req->sconn->ev_ctx,
2459 smbd_smb2_request_dispatch_immediate,
2460 req);
2461 return NT_STATUS_OK;
2464 if (req->compound_related) {
2465 req->compound_related = false;
2468 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2470 /* Set credit for these operations (zero credits if this
2471 is a final reply for an async operation). */
2472 smb2_calculate_credits(req, req);
2475 * now check if we need to sign the current response
2477 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2478 status = smb2_signing_encrypt_pdu(req->first_key,
2479 xconn->protocol,
2480 firsttf,
2481 req->out.vector_count - first_idx);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 return status;
2485 } else if (req->do_signing) {
2486 struct smbXsrv_session *x = req->session;
2487 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2489 status = smb2_signing_sign_pdu(signing_key,
2490 xconn->protocol,
2491 outhdr,
2492 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2493 if (!NT_STATUS_IS_OK(status)) {
2494 return status;
2497 if (req->first_key.length > 0) {
2498 data_blob_clear_free(&req->first_key);
2501 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2502 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2503 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2504 /* Dynamic part is NULL. Chop it off,
2505 We're going to send it via sendfile. */
2506 req->out.vector_count -= 1;
2510 * We're done with this request -
2511 * move it off the "being processed" queue.
2513 DLIST_REMOVE(xconn->smb2.requests, req);
2515 req->queue_entry.mem_ctx = req;
2516 req->queue_entry.vector = req->out.vector;
2517 req->queue_entry.count = req->out.vector_count;
2518 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2519 xconn->smb2.send_queue_len++;
2521 status = smbd_smb2_flush_send_queue(xconn);
2522 if (!NT_STATUS_IS_OK(status)) {
2523 return status;
2526 return NT_STATUS_OK;
2529 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2531 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2532 struct tevent_immediate *im,
2533 void *private_data)
2535 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2536 struct smbd_smb2_request);
2537 struct smbd_server_connection *sconn = req->sconn;
2538 struct smbXsrv_connection *xconn = req->xconn;
2539 NTSTATUS status;
2541 TALLOC_FREE(im);
2543 if (DEBUGLEVEL >= 10) {
2544 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2545 req->current_idx, req->in.vector_count));
2546 print_req_vectors(req);
2549 status = smbd_smb2_request_dispatch(req);
2550 if (!NT_STATUS_IS_OK(status)) {
2551 smbd_server_connection_terminate(sconn, nt_errstr(status));
2552 return;
2555 status = smbd_smb2_request_next_incoming(xconn);
2556 if (!NT_STATUS_IS_OK(status)) {
2557 smbd_server_connection_terminate(sconn, nt_errstr(status));
2558 return;
2562 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2563 NTSTATUS status,
2564 DATA_BLOB body, DATA_BLOB *dyn,
2565 const char *location)
2567 uint8_t *outhdr;
2568 struct iovec *outbody_v;
2569 struct iovec *outdyn_v;
2570 uint32_t next_command_ofs;
2572 DEBUG(10,("smbd_smb2_request_done_ex: "
2573 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2574 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2575 dyn ? "yes": "no",
2576 (unsigned int)(dyn ? dyn->length : 0),
2577 location));
2579 if (body.length < 2) {
2580 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2583 if ((body.length % 2) != 0) {
2584 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2587 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2588 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2589 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2591 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2592 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2594 outbody_v->iov_base = (void *)body.data;
2595 outbody_v->iov_len = body.length;
2597 if (dyn) {
2598 outdyn_v->iov_base = (void *)dyn->data;
2599 outdyn_v->iov_len = dyn->length;
2600 } else {
2601 outdyn_v->iov_base = NULL;
2602 outdyn_v->iov_len = 0;
2605 /* see if we need to recalculate the offset to the next response */
2606 if (next_command_ofs > 0) {
2607 next_command_ofs = SMB2_HDR_BODY;
2608 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2609 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2612 if ((next_command_ofs % 8) != 0) {
2613 size_t pad_size = 8 - (next_command_ofs % 8);
2614 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2616 * if the dyn buffer is empty
2617 * we can use it to add padding
2619 uint8_t *pad;
2621 pad = talloc_zero_array(req,
2622 uint8_t, pad_size);
2623 if (pad == NULL) {
2624 return smbd_smb2_request_error(req,
2625 NT_STATUS_NO_MEMORY);
2628 outdyn_v->iov_base = (void *)pad;
2629 outdyn_v->iov_len = pad_size;
2630 } else {
2632 * For now we copy the dynamic buffer
2633 * and add the padding to the new buffer
2635 size_t old_size;
2636 uint8_t *old_dyn;
2637 size_t new_size;
2638 uint8_t *new_dyn;
2640 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2641 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2643 new_size = old_size + pad_size;
2644 new_dyn = talloc_zero_array(req,
2645 uint8_t, new_size);
2646 if (new_dyn == NULL) {
2647 return smbd_smb2_request_error(req,
2648 NT_STATUS_NO_MEMORY);
2651 memcpy(new_dyn, old_dyn, old_size);
2652 memset(new_dyn + old_size, 0, pad_size);
2654 outdyn_v->iov_base = (void *)new_dyn;
2655 outdyn_v->iov_len = new_size;
2657 next_command_ofs += pad_size;
2660 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2662 return smbd_smb2_request_reply(req);
2665 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2666 NTSTATUS status,
2667 DATA_BLOB *info,
2668 const char *location)
2670 struct smbXsrv_connection *xconn = req->sconn->conn;
2671 DATA_BLOB body;
2672 DATA_BLOB _dyn;
2673 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2674 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2676 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2677 req->current_idx, nt_errstr(status), info ? " +info" : "",
2678 location));
2680 if (unread_bytes) {
2681 /* Recvfile error. Drain incoming socket. */
2682 size_t ret;
2684 errno = 0;
2685 ret = drain_socket(xconn->transport.sock, unread_bytes);
2686 if (ret != unread_bytes) {
2687 NTSTATUS error;
2689 if (errno == 0) {
2690 error = NT_STATUS_IO_DEVICE_ERROR;
2691 } else {
2692 error = map_nt_error_from_unix_common(errno);
2695 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2696 "ret[%u] errno[%d] => %s\n",
2697 (unsigned)unread_bytes,
2698 (unsigned)ret, errno, nt_errstr(error)));
2699 return error;
2703 body.data = outhdr + SMB2_HDR_BODY;
2704 body.length = 8;
2705 SSVAL(body.data, 0, 9);
2707 if (info) {
2708 SIVAL(body.data, 0x04, info->length);
2709 } else {
2710 /* Allocated size of req->out.vector[i].iov_base
2711 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2712 * 1 byte without having to do an alloc.
2714 info = &_dyn;
2715 info->data = ((uint8_t *)outhdr) +
2716 OUTVEC_ALLOC_SIZE - 1;
2717 info->length = 1;
2718 SCVAL(info->data, 0, 0);
2722 * Note: Even if there is an error, continue to process the request.
2723 * per MS-SMB2.
2726 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2730 struct smbd_smb2_send_break_state {
2731 struct smbd_server_connection *sconn;
2732 struct smbd_smb2_send_queue queue_entry;
2733 uint8_t nbt_hdr[NBT_HDR_SIZE];
2734 uint8_t tf[SMB2_TF_HDR_SIZE];
2735 uint8_t hdr[SMB2_HDR_BODY];
2736 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2737 uint8_t body[1];
2740 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2741 struct smbXsrv_session *session,
2742 struct smbXsrv_tcon *tcon,
2743 const uint8_t *body,
2744 size_t body_len)
2746 struct smbd_smb2_send_break_state *state;
2747 struct smbXsrv_connection *xconn = sconn->conn;
2748 bool do_encryption = session->global->encryption_required;
2749 uint64_t nonce_high = 0;
2750 uint64_t nonce_low = 0;
2751 NTSTATUS status;
2752 size_t statelen;
2754 if (tcon->global->encryption_required) {
2755 do_encryption = true;
2758 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2759 body_len;
2761 state = talloc_zero_size(sconn, statelen);
2762 if (state == NULL) {
2763 return NT_STATUS_NO_MEMORY;
2765 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2766 state->sconn = sconn;
2768 if (do_encryption) {
2769 nonce_high = session->nonce_high;
2770 nonce_low = session->nonce_low;
2772 session->nonce_low += 1;
2773 if (session->nonce_low == 0) {
2774 session->nonce_low += 1;
2775 session->nonce_high += 1;
2779 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2780 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2781 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2782 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2784 SIVAL(state->hdr, 0, SMB2_MAGIC);
2785 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2786 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2787 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2788 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2789 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2790 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2791 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2792 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2793 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2794 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2795 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2796 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2798 state->vector[0] = (struct iovec) {
2799 .iov_base = state->nbt_hdr,
2800 .iov_len = sizeof(state->nbt_hdr)
2803 if (do_encryption) {
2804 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2805 .iov_base = state->tf,
2806 .iov_len = sizeof(state->tf)
2808 } else {
2809 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2810 .iov_base = NULL,
2811 .iov_len = 0
2815 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2816 .iov_base = state->hdr,
2817 .iov_len = sizeof(state->hdr)
2820 memcpy(state->body, body, body_len);
2822 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2823 .iov_base = state->body,
2824 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2828 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2831 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2833 if (do_encryption) {
2834 DATA_BLOB encryption_key = session->global->encryption_key;
2836 status = smb2_signing_encrypt_pdu(encryption_key,
2837 xconn->protocol,
2838 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2839 SMBD_SMB2_NUM_IOV_PER_REQ);
2840 if (!NT_STATUS_IS_OK(status)) {
2841 return status;
2845 state->queue_entry.mem_ctx = state;
2846 state->queue_entry.vector = state->vector;
2847 state->queue_entry.count = ARRAY_SIZE(state->vector);
2848 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2849 xconn->smb2.send_queue_len++;
2851 status = smbd_smb2_flush_send_queue(xconn);
2852 if (!NT_STATUS_IS_OK(status)) {
2853 return status;
2856 return NT_STATUS_OK;
2859 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2860 struct smbXsrv_session *session,
2861 struct smbXsrv_tcon *tcon,
2862 struct smbXsrv_open *op,
2863 uint8_t oplock_level)
2865 uint8_t body[0x18];
2867 SSVAL(body, 0x00, sizeof(body));
2868 SCVAL(body, 0x02, oplock_level);
2869 SCVAL(body, 0x03, 0); /* reserved */
2870 SIVAL(body, 0x04, 0); /* reserved */
2871 SBVAL(body, 0x08, op->global->open_persistent_id);
2872 SBVAL(body, 0x10, op->global->open_volatile_id);
2874 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2877 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2879 NTSTATUS status;
2880 uint32_t flags;
2881 uint64_t file_id_persistent;
2882 uint64_t file_id_volatile;
2883 struct smbXsrv_open *op = NULL;
2884 struct files_struct *fsp = NULL;
2885 const uint8_t *body = NULL;
2888 * This is only called with a pktbuf
2889 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2890 * bytes
2893 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2894 /* Transform header. Cannot recvfile. */
2895 return false;
2897 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2898 /* Not SMB2. Normal error path will cope. */
2899 return false;
2901 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2902 /* Not SMB2. Normal error path will cope. */
2903 return false;
2905 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2906 /* Needs to be a WRITE. */
2907 return false;
2909 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2910 /* Chained. Cannot recvfile. */
2911 return false;
2913 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2914 if (flags & SMB2_HDR_FLAG_CHAINED) {
2915 /* Chained. Cannot recvfile. */
2916 return false;
2918 if (flags & SMB2_HDR_FLAG_SIGNED) {
2919 /* Signed. Cannot recvfile. */
2920 return false;
2923 body = &state->pktbuf[SMB2_HDR_BODY];
2925 file_id_persistent = BVAL(body, 0x10);
2926 file_id_volatile = BVAL(body, 0x18);
2928 status = smb2srv_open_lookup(state->req->sconn->conn,
2929 file_id_persistent,
2930 file_id_volatile,
2931 0, /* now */
2932 &op);
2933 if (!NT_STATUS_IS_OK(status)) {
2934 return false;
2937 fsp = op->compat;
2938 if (fsp == NULL) {
2939 return false;
2941 if (fsp->conn == NULL) {
2942 return false;
2945 if (IS_IPC(fsp->conn)) {
2946 return false;
2948 if (IS_PRINT(fsp->conn)) {
2949 return false;
2952 DEBUG(10,("Doing recvfile write len = %u\n",
2953 (unsigned int)(state->pktfull - state->pktlen)));
2955 return true;
2958 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2960 struct smbd_server_connection *sconn = xconn->sconn;
2961 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2962 size_t max_send_queue_len;
2963 size_t cur_send_queue_len;
2965 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2967 * we're not supposed to do any io
2969 return NT_STATUS_OK;
2972 if (state->req != NULL) {
2974 * if there is already a tstream_readv_pdu
2975 * pending, we are done.
2977 return NT_STATUS_OK;
2980 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2981 cur_send_queue_len = xconn->smb2.send_queue_len;
2983 if (cur_send_queue_len > max_send_queue_len) {
2985 * if we have a lot of requests to send,
2986 * we wait until they are on the wire until we
2987 * ask for the next request.
2989 return NT_STATUS_OK;
2992 /* ask for the next request */
2993 ZERO_STRUCTP(state);
2994 state->req = smbd_smb2_request_allocate(xconn);
2995 if (state->req == NULL) {
2996 return NT_STATUS_NO_MEMORY;
2998 state->req->sconn = sconn;
2999 state->req->xconn = xconn;
3000 state->min_recv_size = lp_min_receive_file_size();
3002 TEVENT_FD_READABLE(xconn->transport.fde);
3004 return NT_STATUS_OK;
3007 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3008 uint8_t *inbuf, size_t size)
3010 struct smbd_server_connection *sconn = xconn->sconn;
3011 NTSTATUS status;
3012 struct smbd_smb2_request *req = NULL;
3014 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3015 (unsigned int)size));
3017 status = smbd_initialize_smb2(xconn);
3018 if (!NT_STATUS_IS_OK(status)) {
3019 smbd_server_connection_terminate(sconn, nt_errstr(status));
3020 return;
3023 status = smbd_smb2_request_create(xconn, inbuf, size, &req);
3024 if (!NT_STATUS_IS_OK(status)) {
3025 smbd_server_connection_terminate(sconn, nt_errstr(status));
3026 return;
3029 status = smbd_smb2_request_validate(req);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 smbd_server_connection_terminate(sconn, nt_errstr(status));
3032 return;
3035 status = smbd_smb2_request_setup_out(req);
3036 if (!NT_STATUS_IS_OK(status)) {
3037 smbd_server_connection_terminate(sconn, nt_errstr(status));
3038 return;
3041 status = smbd_smb2_request_dispatch(req);
3042 if (!NT_STATUS_IS_OK(status)) {
3043 smbd_server_connection_terminate(sconn, nt_errstr(status));
3044 return;
3047 status = smbd_smb2_request_next_incoming(xconn);
3048 if (!NT_STATUS_IS_OK(status)) {
3049 smbd_server_connection_terminate(sconn, nt_errstr(status));
3050 return;
3053 sconn->num_requests++;
3056 static int socket_error_from_errno(int ret,
3057 int sys_errno,
3058 bool *retry)
3060 *retry = false;
3062 if (ret >= 0) {
3063 return 0;
3066 if (ret != -1) {
3067 return EIO;
3070 if (sys_errno == 0) {
3071 return EIO;
3074 if (sys_errno == EINTR) {
3075 *retry = true;
3076 return sys_errno;
3079 if (sys_errno == EINPROGRESS) {
3080 *retry = true;
3081 return sys_errno;
3084 if (sys_errno == EAGAIN) {
3085 *retry = true;
3086 return sys_errno;
3089 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3090 if (sys_errno == ENOMEM) {
3091 *retry = true;
3092 return sys_errno;
3095 #ifdef EWOULDBLOCK
3096 #if EWOULDBLOCK != EAGAIN
3097 if (sys_errno == EWOULDBLOCK) {
3098 *retry = true;
3099 return sys_errno;
3101 #endif
3102 #endif
3104 return sys_errno;
3107 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3109 int ret;
3110 int err;
3111 bool retry;
3113 if (xconn->smb2.send_queue == NULL) {
3114 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3115 return NT_STATUS_OK;
3118 while (xconn->smb2.send_queue != NULL) {
3119 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3121 if (e->sendfile_header != NULL) {
3122 size_t size = 0;
3123 size_t i = 0;
3124 uint8_t *buf;
3126 for (i=0; i < e->count; i++) {
3127 size += e->vector[i].iov_len;
3130 if (size <= e->sendfile_header->length) {
3131 buf = e->sendfile_header->data;
3132 } else {
3133 buf = talloc_array(e->mem_ctx, uint8_t, size);
3134 if (buf == NULL) {
3135 return NT_STATUS_NO_MEMORY;
3139 size = 0;
3140 for (i=0; i < e->count; i++) {
3141 memcpy(buf+size,
3142 e->vector[i].iov_base,
3143 e->vector[i].iov_len);
3144 size += e->vector[i].iov_len;
3147 e->sendfile_header->data = buf;
3148 e->sendfile_header->length = size;
3149 e->count = 0;
3151 xconn->smb2.send_queue_len--;
3152 DLIST_REMOVE(xconn->smb2.send_queue, e);
3154 * This triggers the sendfile path via
3155 * the destructor.
3157 talloc_free(e->mem_ctx);
3158 continue;
3161 ret = writev(xconn->transport.sock, e->vector, e->count);
3162 if (ret == 0) {
3163 /* propagate end of file */
3164 return NT_STATUS_INTERNAL_ERROR;
3166 err = socket_error_from_errno(ret, errno, &retry);
3167 if (retry) {
3168 /* retry later */
3169 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3170 return NT_STATUS_OK;
3172 if (err != 0) {
3173 return map_nt_error_from_unix_common(err);
3175 while (ret > 0) {
3176 if (ret < e->vector[0].iov_len) {
3177 uint8_t *base;
3178 base = (uint8_t *)e->vector[0].iov_base;
3179 base += ret;
3180 e->vector[0].iov_base = (void *)base;
3181 e->vector[0].iov_len -= ret;
3182 break;
3184 ret -= e->vector[0].iov_len;
3185 e->vector += 1;
3186 e->count -= 1;
3190 * there're maybe some empty vectors at the end
3191 * which we need to skip, otherwise we would get
3192 * ret == 0 from the readv() call and return EPIPE
3194 while (e->count > 0) {
3195 if (e->vector[0].iov_len > 0) {
3196 break;
3198 e->vector += 1;
3199 e->count -= 1;
3202 if (e->count > 0) {
3203 /* we have more to write */
3204 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3205 return NT_STATUS_OK;
3208 xconn->smb2.send_queue_len--;
3209 DLIST_REMOVE(xconn->smb2.send_queue, e);
3210 talloc_free(e->mem_ctx);
3213 return NT_STATUS_OK;
3216 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3217 uint16_t fde_flags)
3219 struct smbd_server_connection *sconn = xconn->sconn;
3220 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3221 struct smbd_smb2_request *req = NULL;
3222 size_t min_recvfile_size = UINT32_MAX;
3223 int ret;
3224 int err;
3225 bool retry;
3226 NTSTATUS status;
3227 NTTIME now;
3229 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3231 * we're not supposed to do any io
3233 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3234 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3235 return NT_STATUS_OK;
3238 if (fde_flags & TEVENT_FD_WRITE) {
3239 status = smbd_smb2_flush_send_queue(xconn);
3240 if (!NT_STATUS_IS_OK(status)) {
3241 return status;
3245 if (!(fde_flags & TEVENT_FD_READ)) {
3246 return NT_STATUS_OK;
3249 if (state->req == NULL) {
3250 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3251 return NT_STATUS_OK;
3254 again:
3255 if (!state->hdr.done) {
3256 state->hdr.done = true;
3258 state->vector.iov_base = (void *)state->hdr.nbt;
3259 state->vector.iov_len = NBT_HDR_SIZE;
3262 ret = readv(xconn->transport.sock, &state->vector, 1);
3263 if (ret == 0) {
3264 /* propagate end of file */
3265 return NT_STATUS_END_OF_FILE;
3267 err = socket_error_from_errno(ret, errno, &retry);
3268 if (retry) {
3269 /* retry later */
3270 TEVENT_FD_READABLE(xconn->transport.fde);
3271 return NT_STATUS_OK;
3273 if (err != 0) {
3274 return map_nt_error_from_unix_common(err);
3277 if (ret < state->vector.iov_len) {
3278 uint8_t *base;
3279 base = (uint8_t *)state->vector.iov_base;
3280 base += ret;
3281 state->vector.iov_base = (void *)base;
3282 state->vector.iov_len -= ret;
3283 /* we have more to read */
3284 TEVENT_FD_READABLE(xconn->transport.fde);
3285 return NT_STATUS_OK;
3288 if (state->pktlen > 0) {
3289 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3291 * Not a possible receivefile write.
3292 * Read the rest of the data.
3294 state->doing_receivefile = false;
3296 state->pktbuf = talloc_realloc(state->req,
3297 state->pktbuf,
3298 uint8_t,
3299 state->pktfull);
3300 if (state->pktbuf == NULL) {
3301 return NT_STATUS_NO_MEMORY;
3304 state->vector.iov_base = (void *)(state->pktbuf +
3305 state->pktlen);
3306 state->vector.iov_len = (state->pktfull -
3307 state->pktlen);
3309 state->pktlen = state->pktfull;
3310 goto again;
3314 * Either this is a receivefile write so we've
3315 * done a short read, or if not we have all the data.
3317 goto got_full;
3321 * Now we analyze the NBT header
3323 if (state->hdr.nbt[0] != 0x00) {
3324 state->min_recv_size = 0;
3326 state->pktfull = smb2_len(state->hdr.nbt);
3327 if (state->pktfull == 0) {
3328 goto got_full;
3331 if (state->min_recv_size != 0) {
3332 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3333 min_recvfile_size += state->min_recv_size;
3336 if (state->pktfull > min_recvfile_size) {
3338 * Might be a receivefile write. Read the SMB2 HEADER +
3339 * SMB2_WRITE header first. Set 'doing_receivefile'
3340 * as we're *attempting* receivefile write. If this
3341 * turns out not to be a SMB2_WRITE request or otherwise
3342 * not suitable then we'll just read the rest of the data
3343 * the next time this function is called.
3345 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3346 state->doing_receivefile = true;
3347 } else {
3348 state->pktlen = state->pktfull;
3351 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3352 if (state->pktbuf == NULL) {
3353 return NT_STATUS_NO_MEMORY;
3356 state->vector.iov_base = (void *)state->pktbuf;
3357 state->vector.iov_len = state->pktlen;
3359 goto again;
3361 got_full:
3363 if (state->hdr.nbt[0] != 0x00) {
3364 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3365 state->hdr.nbt[0]));
3367 req = state->req;
3368 ZERO_STRUCTP(state);
3369 state->req = req;
3370 state->min_recv_size = lp_min_receive_file_size();
3371 req = NULL;
3372 goto again;
3375 req = state->req;
3376 state->req = NULL;
3378 req->request_time = timeval_current();
3379 now = timeval_to_nttime(&req->request_time);
3381 status = smbd_smb2_inbuf_parse_compound(xconn,
3382 now,
3383 state->pktbuf,
3384 state->pktlen,
3385 req,
3386 &req->in.vector,
3387 &req->in.vector_count);
3388 if (!NT_STATUS_IS_OK(status)) {
3389 return status;
3392 if (state->doing_receivefile) {
3393 req->smb1req = talloc_zero(req, struct smb_request);
3394 if (req->smb1req == NULL) {
3395 return NT_STATUS_NO_MEMORY;
3397 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3400 ZERO_STRUCTP(state);
3402 req->current_idx = 1;
3404 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3405 req->current_idx, req->in.vector_count));
3407 status = smbd_smb2_request_validate(req);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 return status;
3412 status = smbd_smb2_request_setup_out(req);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 return status;
3417 status = smbd_smb2_request_dispatch(req);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 return status;
3422 sconn->num_requests++;
3424 /* The timeout_processing function isn't run nearly
3425 often enough to implement 'max log size' without
3426 overrunning the size of the file by many megabytes.
3427 This is especially true if we are running at debug
3428 level 10. Checking every 50 SMB2s is a nice
3429 tradeoff of performance vs log file size overrun. */
3431 if ((sconn->num_requests % 50) == 0 &&
3432 need_to_check_log_size()) {
3433 change_to_root_user();
3434 check_log_size();
3437 status = smbd_smb2_request_next_incoming(xconn);
3438 if (!NT_STATUS_IS_OK(status)) {
3439 return status;
3442 return NT_STATUS_OK;
3445 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3446 struct tevent_fd *fde,
3447 uint16_t flags,
3448 void *private_data)
3450 struct smbXsrv_connection *xconn =
3451 talloc_get_type_abort(private_data,
3452 struct smbXsrv_connection);
3453 struct smbd_server_connection *sconn = xconn->sconn;
3454 NTSTATUS status;
3456 status = smbd_smb2_io_handler(xconn, flags);
3457 if (!NT_STATUS_IS_OK(status)) {
3458 smbd_server_connection_terminate(sconn, nt_errstr(status));
3459 return;