s3:smb2_server: pass smbXsrv_connection to smb2_set_operation_credit()
[Samba.git] / source3 / smbd / smb2_server.c
blobeee08f1cd88290f083545a174f0fea7397f4798a
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 smbd_server_connection *sconn)
203 struct smbXsrv_connection *xconn = sconn->conn;
205 TALLOC_FREE(xconn->transport.fde);
207 xconn->smb2.credits.seq_low = 0;
208 xconn->smb2.credits.seq_range = 1;
209 xconn->smb2.credits.granted = 1;
210 xconn->smb2.credits.max = lp_smb2_max_credits();
211 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
212 xconn->smb2.credits.max);
213 if (xconn->smb2.credits.bitmap == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
218 xconn,
219 xconn->transport.sock,
220 TEVENT_FD_READ,
221 smbd_smb2_connection_handler,
222 xconn);
223 if (xconn->transport.fde == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(xconn->transport.sock, false);
229 return NT_STATUS_OK;
232 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
233 #define _smb2_setlen(_buf,len) do { \
234 uint8_t *buf = (uint8_t *)_buf; \
235 buf[0] = 0; \
236 buf[1] = ((len)&0xFF0000)>>16; \
237 buf[2] = ((len)&0xFF00)>>8; \
238 buf[3] = (len)&0xFF; \
239 } while (0)
241 static void smb2_setup_nbt_length(struct iovec *vector, int count)
243 size_t len = 0;
244 int i;
246 for (i=1; i < count; i++) {
247 len += vector[i].iov_len;
250 _smb2_setlen(vector[0].iov_base, len);
253 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
255 if (req->first_key.length > 0) {
256 data_blob_clear_free(&req->first_key);
258 if (req->last_key.length > 0) {
259 data_blob_clear_free(&req->last_key);
261 return 0;
264 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
266 TALLOC_CTX *mem_pool;
267 struct smbd_smb2_request *req;
269 #if 0
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 #else
273 mem_pool = talloc_tos();
274 #endif
275 if (mem_pool == NULL) {
276 return NULL;
279 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 if (req == NULL) {
281 talloc_free(mem_pool);
282 return NULL;
284 talloc_reparent(mem_pool, mem_ctx, req);
285 #if 0
286 TALLOC_FREE(mem_pool);
287 #endif
289 req->last_session_id = UINT64_MAX;
290 req->last_tid = UINT32_MAX;
292 talloc_set_destructor(req, smbd_smb2_request_destructor);
294 return req;
297 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
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 (xconn->protocol < PROTOCOL_SMB2_24) {
355 DEBUG(10, ("Got SMB2_TRANSFORM header, "
356 "but dialect[0x%04X] is used\n",
357 xconn->smb2.server.dialect));
358 goto inval;
361 if (!(xconn->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 xconn->smb2.client.capabilities,
366 xconn->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(xconn, 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 xconn->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 smbXsrv_connection *xconn = sconn->conn;
515 struct smbd_smb2_request *req;
516 uint32_t protocol_version;
517 const uint8_t *inhdr = NULL;
518 uint16_t cmd;
519 uint32_t next_command_ofs;
520 NTSTATUS status;
521 NTTIME now;
523 if (size < (4 + SMB2_HDR_BODY + 2)) {
524 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
525 return NT_STATUS_INVALID_PARAMETER;
528 inhdr = inbuf + 4;
530 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
531 if (protocol_version != SMB2_MAGIC) {
532 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
533 protocol_version));
534 return NT_STATUS_INVALID_PARAMETER;
537 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
538 if (cmd != SMB2_OP_NEGPROT) {
539 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
540 cmd));
541 return NT_STATUS_INVALID_PARAMETER;
544 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
545 if (next_command_ofs != 0) {
546 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
547 next_command_ofs));
548 return NT_STATUS_INVALID_PARAMETER;
551 req = smbd_smb2_request_allocate(xconn);
552 if (req == NULL) {
553 return NT_STATUS_NO_MEMORY;
555 req->sconn = sconn;
556 req->xconn = xconn;
558 talloc_steal(req, inbuf);
560 req->request_time = timeval_current();
561 now = timeval_to_nttime(&req->request_time);
563 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
564 now,
565 inbuf + NBT_HDR_SIZE,
566 size - NBT_HDR_SIZE,
567 req, &req->in.vector,
568 &req->in.vector_count);
569 if (!NT_STATUS_IS_OK(status)) {
570 TALLOC_FREE(req);
571 return status;
574 req->current_idx = 1;
576 *_req = req;
577 return NT_STATUS_OK;
580 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
581 uint64_t message_id, uint64_t seq_id)
583 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
584 unsigned int offset;
585 uint64_t seq_tmp;
587 seq_tmp = xconn->smb2.credits.seq_low;
588 if (seq_id < seq_tmp) {
589 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
590 "%llu (sequence id %llu) "
591 "(granted = %u, low = %llu, range = %u)\n",
592 (unsigned long long)message_id,
593 (unsigned long long)seq_id,
594 (unsigned int)xconn->smb2.credits.granted,
595 (unsigned long long)xconn->smb2.credits.seq_low,
596 (unsigned int)xconn->smb2.credits.seq_range));
597 return false;
600 seq_tmp += xconn->smb2.credits.seq_range;
601 if (seq_id >= seq_tmp) {
602 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
603 "%llu (sequence id %llu) "
604 "(granted = %u, low = %llu, range = %u)\n",
605 (unsigned long long)message_id,
606 (unsigned long long)seq_id,
607 (unsigned int)xconn->smb2.credits.granted,
608 (unsigned long long)xconn->smb2.credits.seq_low,
609 (unsigned int)xconn->smb2.credits.seq_range));
610 return false;
613 offset = seq_id % xconn->smb2.credits.max;
615 if (bitmap_query(credits_bm, offset)) {
616 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
617 "%llu (sequence id %llu) "
618 "(granted = %u, low = %llu, range = %u) "
619 "(bm offset %u)\n",
620 (unsigned long long)message_id,
621 (unsigned long long)seq_id,
622 (unsigned int)xconn->smb2.credits.granted,
623 (unsigned long long)xconn->smb2.credits.seq_low,
624 (unsigned int)xconn->smb2.credits.seq_range,
625 offset));
626 return false;
629 /* Mark the message_ids as seen in the bitmap. */
630 bitmap_set(credits_bm, offset);
632 if (seq_id != xconn->smb2.credits.seq_low) {
633 return true;
637 * Move the window forward by all the message_id's
638 * already seen.
640 while (bitmap_query(credits_bm, offset)) {
641 DEBUG(10,("smb2_validate_sequence_number: clearing "
642 "id %llu (position %u) from bitmap\n",
643 (unsigned long long)(xconn->smb2.credits.seq_low),
644 offset));
645 bitmap_clear(credits_bm, offset);
647 xconn->smb2.credits.seq_low += 1;
648 xconn->smb2.credits.seq_range -= 1;
649 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
652 return true;
655 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
656 const uint8_t *inhdr)
658 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
659 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
660 uint16_t credit_charge = 1;
661 uint64_t i;
663 if (opcode == SMB2_OP_CANCEL) {
664 /* SMB2_CANCEL requests by definition resend messageids. */
665 return true;
668 if (xconn->smb2.credits.multicredit) {
669 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
670 credit_charge = MAX(credit_charge, 1);
673 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
674 "credits_granted %llu, "
675 "seqnum low/range: %llu/%llu\n",
676 (unsigned long long) message_id,
677 (unsigned long long) credit_charge,
678 (unsigned long long) xconn->smb2.credits.granted,
679 (unsigned long long) xconn->smb2.credits.seq_low,
680 (unsigned long long) xconn->smb2.credits.seq_range));
682 if (xconn->smb2.credits.granted < credit_charge) {
683 DEBUG(0, ("smb2_validate_message_id: client used more "
684 "credits than granted, mid %llu, charge %llu, "
685 "credits_granted %llu, "
686 "seqnum low/range: %llu/%llu\n",
687 (unsigned long long) message_id,
688 (unsigned long long) credit_charge,
689 (unsigned long long) xconn->smb2.credits.granted,
690 (unsigned long long) xconn->smb2.credits.seq_low,
691 (unsigned long long) xconn->smb2.credits.seq_range));
692 return false;
696 * now check the message ids
698 * for multi-credit requests we need to check all current mid plus
699 * the implicit mids caused by the credit charge
700 * e.g. current mid = 15, charge 5 => mark 15-19 as used
703 for (i = 0; i <= (credit_charge-1); i++) {
704 uint64_t id = message_id + i;
705 bool ok;
707 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
708 (unsigned long long)message_id,
709 credit_charge,
710 (unsigned long long)id));
712 ok = smb2_validate_sequence_number(xconn, message_id, id);
713 if (!ok) {
714 return false;
718 /* substract used credits */
719 xconn->smb2.credits.granted -= credit_charge;
721 return true;
724 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
726 int count;
727 int idx;
729 count = req->in.vector_count;
731 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
732 /* It's not a SMB2 request */
733 return NT_STATUS_INVALID_PARAMETER;
736 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
737 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
738 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
739 const uint8_t *inhdr = NULL;
741 if (hdr->iov_len != SMB2_HDR_BODY) {
742 return NT_STATUS_INVALID_PARAMETER;
745 if (body->iov_len < 2) {
746 return NT_STATUS_INVALID_PARAMETER;
749 inhdr = (const uint8_t *)hdr->iov_base;
751 /* Check the SMB2 header */
752 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
753 return NT_STATUS_INVALID_PARAMETER;
756 if (!smb2_validate_message_id(req->xconn, inhdr)) {
757 return NT_STATUS_INVALID_PARAMETER;
761 return NT_STATUS_OK;
764 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
765 const struct iovec *in_vector,
766 struct iovec *out_vector)
768 struct smbd_server_connection *sconn = xconn->sconn;
769 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
770 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
771 uint16_t credit_charge = 1;
772 uint16_t credits_requested;
773 uint32_t out_flags;
774 uint16_t cmd;
775 NTSTATUS out_status;
776 uint16_t credits_granted = 0;
777 uint64_t credits_possible;
778 uint16_t current_max_credits;
781 * first we grant only 1/16th of the max range.
783 * Windows also starts with the 1/16th and then grants
784 * more later. I was only able to trigger higher
785 * values, when using a very high credit charge.
787 * TODO: scale up depending on load, free memory
788 * or other stuff.
789 * Maybe also on the relationship between number
790 * of requests and the used sequence number.
791 * Which means we would grant more credits
792 * for client which use multi credit requests.
794 current_max_credits = xconn->smb2.credits.max / 16;
795 current_max_credits = MAX(current_max_credits, 1);
797 if (xconn->smb2.credits.multicredit) {
798 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
799 credit_charge = MAX(credit_charge, 1);
802 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
803 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
804 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
805 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
807 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
809 if (xconn->smb2.credits.max < credit_charge) {
810 smbd_server_connection_terminate(sconn,
811 "client error: credit charge > max credits\n");
812 return;
815 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
817 * In case we already send an async interim
818 * response, we should not grant
819 * credits on the final response.
821 credits_granted = 0;
822 } else if (credits_requested > 0) {
823 uint16_t additional_max = 0;
824 uint16_t additional_credits = credits_requested - 1;
826 switch (cmd) {
827 case SMB2_OP_NEGPROT:
828 break;
829 case SMB2_OP_SESSSETUP:
831 * Windows 2012 RC1 starts to grant
832 * additional credits
833 * with a successful session setup
835 if (NT_STATUS_IS_OK(out_status)) {
836 additional_max = 32;
838 break;
839 default:
841 * We match windows and only grant additional credits
842 * in chunks of 32.
844 additional_max = 32;
845 break;
848 additional_credits = MIN(additional_credits, additional_max);
850 credits_granted = credit_charge + additional_credits;
851 } else if (xconn->smb2.credits.granted == 0) {
853 * Make sure the client has always at least one credit
855 credits_granted = 1;
859 * sequence numbers should not wrap
861 * 1. calculate the possible credits until
862 * the sequence numbers start to wrap on 64-bit.
864 * 2. UINT64_MAX is used for Break Notifications.
866 * 2. truncate the possible credits to the maximum
867 * credits we want to grant to the client in total.
869 * 3. remove the range we'll already granted to the client
870 * this makes sure the client consumes the lowest sequence
871 * number, before we can grant additional credits.
873 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
874 if (credits_possible > 0) {
875 /* remove UINT64_MAX */
876 credits_possible -= 1;
878 credits_possible = MIN(credits_possible, current_max_credits);
879 credits_possible -= xconn->smb2.credits.seq_range;
881 credits_granted = MIN(credits_granted, credits_possible);
883 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
884 xconn->smb2.credits.granted += credits_granted;
885 xconn->smb2.credits.seq_range += credits_granted;
887 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
888 "granted %u, current possible/max %u/%u, "
889 "total granted/max/low/range %u/%u/%llu/%u\n",
890 (unsigned int)credits_requested,
891 (unsigned int)credit_charge,
892 (unsigned int)credits_granted,
893 (unsigned int)credits_possible,
894 (unsigned int)current_max_credits,
895 (unsigned int)xconn->smb2.credits.granted,
896 (unsigned int)xconn->smb2.credits.max,
897 (unsigned long long)xconn->smb2.credits.seq_low,
898 (unsigned int)xconn->smb2.credits.seq_range));
901 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
902 struct smbd_smb2_request *outreq)
904 int count, idx;
905 uint16_t total_credits = 0;
907 count = outreq->out.vector_count;
909 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
910 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
911 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
912 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
914 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
916 /* To match Windows, count up what we
917 just granted. */
918 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
919 /* Set to zero in all but the last reply. */
920 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
921 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
922 } else {
923 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
928 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
930 if (req->current_idx <= 1) {
931 if (size <= sizeof(req->out._body)) {
932 return data_blob_const(req->out._body, size);
936 return data_blob_talloc(req, NULL, size);
939 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
941 struct smbXsrv_connection *xconn = req->sconn->conn;
942 TALLOC_CTX *mem_ctx;
943 struct iovec *vector;
944 int count;
945 int idx;
947 count = req->in.vector_count;
948 if (count <= ARRAY_SIZE(req->out._vector)) {
949 mem_ctx = req;
950 vector = req->out._vector;
951 } else {
952 vector = talloc_zero_array(req, struct iovec, count);
953 if (vector == NULL) {
954 return NT_STATUS_NO_MEMORY;
956 mem_ctx = vector;
959 vector[0].iov_base = req->out.nbt_hdr;
960 vector[0].iov_len = 4;
961 SIVAL(req->out.nbt_hdr, 0, 0);
963 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
964 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
965 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
966 uint8_t *outhdr = NULL;
967 uint8_t *outbody = NULL;
968 uint32_t next_command_ofs = 0;
969 struct iovec *current = &vector[idx];
971 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
972 /* we have a next command -
973 * setup for the error case. */
974 next_command_ofs = SMB2_HDR_BODY + 9;
977 if (idx == 1) {
978 outhdr = req->out._hdr;
979 } else {
980 outhdr = talloc_zero_array(mem_ctx, uint8_t,
981 OUTVEC_ALLOC_SIZE);
982 if (outhdr == NULL) {
983 return NT_STATUS_NO_MEMORY;
987 outbody = outhdr + SMB2_HDR_BODY;
990 * SMBD_SMB2_TF_IOV_OFS might be used later
992 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
993 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
995 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
996 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
998 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
999 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1001 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1002 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1004 /* setup the SMB2 header */
1005 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1006 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1007 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1008 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1009 SIVAL(outhdr, SMB2_HDR_STATUS,
1010 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1011 SSVAL(outhdr, SMB2_HDR_OPCODE,
1012 SVAL(inhdr, SMB2_HDR_OPCODE));
1013 SIVAL(outhdr, SMB2_HDR_FLAGS,
1014 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1015 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1016 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1017 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1018 SIVAL(outhdr, SMB2_HDR_PID,
1019 IVAL(inhdr, SMB2_HDR_PID));
1020 SIVAL(outhdr, SMB2_HDR_TID,
1021 IVAL(inhdr, SMB2_HDR_TID));
1022 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1023 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1024 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1025 inhdr + SMB2_HDR_SIGNATURE, 16);
1027 /* setup error body header */
1028 SSVAL(outbody, 0x00, 0x08 + 1);
1029 SSVAL(outbody, 0x02, 0);
1030 SIVAL(outbody, 0x04, 0);
1033 req->out.vector = vector;
1034 req->out.vector_count = count;
1036 /* setup the length of the NBT packet */
1037 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1039 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1041 return NT_STATUS_OK;
1044 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1045 const char *reason,
1046 const char *location)
1048 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1049 reason, location));
1050 exit_server_cleanly(reason);
1053 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1054 struct iovec *outvec,
1055 const struct iovec *srcvec)
1057 const uint8_t *srctf;
1058 size_t srctf_len;
1059 const uint8_t *srchdr;
1060 size_t srchdr_len;
1061 const uint8_t *srcbody;
1062 size_t srcbody_len;
1063 const uint8_t *expected_srcbody;
1064 const uint8_t *srcdyn;
1065 size_t srcdyn_len;
1066 const uint8_t *expected_srcdyn;
1067 uint8_t *dsttf;
1068 uint8_t *dsthdr;
1069 uint8_t *dstbody;
1070 uint8_t *dstdyn;
1072 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1073 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1074 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1075 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1076 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1077 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1078 expected_srcbody = srchdr + SMB2_HDR_BODY;
1079 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1080 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1081 expected_srcdyn = srcbody + 8;
1083 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1084 return false;
1087 if (srchdr_len != SMB2_HDR_BODY) {
1088 return false;
1091 if (srctf_len == SMB2_TF_HDR_SIZE) {
1092 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1093 if (dsttf == NULL) {
1094 return false;
1096 } else {
1097 dsttf = NULL;
1099 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1100 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1102 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1103 * be allocated with size OUTVEC_ALLOC_SIZE. */
1105 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1106 if (dsthdr == NULL) {
1107 return false;
1109 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1110 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1113 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1114 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1115 * then duplicate this. Else use talloc_memdup().
1118 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1119 dstbody = dsthdr + SMB2_HDR_BODY;
1120 } else {
1121 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1122 if (dstbody == NULL) {
1123 return false;
1126 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1127 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1130 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1131 * pointing to
1132 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1133 * then duplicate this. Else use talloc_memdup().
1136 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1137 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1138 } else if (srcdyn == NULL) {
1139 dstdyn = NULL;
1140 } else {
1141 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1142 if (dstdyn == NULL) {
1143 return false;
1146 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1147 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1149 return true;
1152 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1154 struct smbd_smb2_request *newreq = NULL;
1155 struct iovec *outvec = NULL;
1156 int count = req->out.vector_count;
1157 int i;
1159 newreq = smbd_smb2_request_allocate(req->xconn);
1160 if (!newreq) {
1161 return NULL;
1164 newreq->sconn = req->sconn;
1165 newreq->xconn = req->xconn;
1166 newreq->session = req->session;
1167 newreq->do_encryption = req->do_encryption;
1168 newreq->do_signing = req->do_signing;
1169 newreq->current_idx = req->current_idx;
1171 outvec = talloc_zero_array(newreq, struct iovec, count);
1172 if (!outvec) {
1173 TALLOC_FREE(newreq);
1174 return NULL;
1176 newreq->out.vector = outvec;
1177 newreq->out.vector_count = count;
1179 /* Setup the outvec's identically to req. */
1180 outvec[0].iov_base = newreq->out.nbt_hdr;
1181 outvec[0].iov_len = 4;
1182 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1184 /* Setup the vectors identically to the ones in req. */
1185 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1186 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1187 break;
1191 if (i < count) {
1192 /* Alloc failed. */
1193 TALLOC_FREE(newreq);
1194 return NULL;
1197 smb2_setup_nbt_length(newreq->out.vector,
1198 newreq->out.vector_count);
1200 return newreq;
1203 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1205 struct smbXsrv_connection *xconn = req->xconn;
1206 int first_idx = 1;
1207 struct iovec *firsttf = NULL;
1208 struct iovec *outhdr_v = NULL;
1209 uint8_t *outhdr = NULL;
1210 struct smbd_smb2_request *nreq = NULL;
1211 NTSTATUS status;
1213 /* Create a new smb2 request we'll use
1214 for the interim return. */
1215 nreq = dup_smb2_req(req);
1216 if (!nreq) {
1217 return NT_STATUS_NO_MEMORY;
1220 /* Lose the last X out vectors. They're the
1221 ones we'll be using for the async reply. */
1222 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1224 smb2_setup_nbt_length(nreq->out.vector,
1225 nreq->out.vector_count);
1227 /* Step back to the previous reply. */
1228 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1229 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1230 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1231 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1232 /* And end the chain. */
1233 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1235 /* Calculate outgoing credits */
1236 smb2_calculate_credits(req, nreq);
1238 if (DEBUGLEVEL >= 10) {
1239 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1240 (unsigned int)nreq->current_idx );
1241 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1242 (unsigned int)nreq->out.vector_count );
1243 print_req_vectors(nreq);
1247 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1248 * we need to sign/encrypt here with the last/first key we remembered
1250 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1251 status = smb2_signing_encrypt_pdu(req->first_key,
1252 xconn->protocol,
1253 firsttf,
1254 nreq->out.vector_count - first_idx);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 return status;
1258 } else if (req->last_key.length > 0) {
1259 status = smb2_signing_sign_pdu(req->last_key,
1260 xconn->protocol,
1261 outhdr_v,
1262 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 return status;
1268 nreq->queue_entry.mem_ctx = nreq;
1269 nreq->queue_entry.vector = nreq->out.vector;
1270 nreq->queue_entry.count = nreq->out.vector_count;
1271 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1272 xconn->smb2.send_queue_len++;
1274 status = smbd_smb2_flush_send_queue(xconn);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 return status;
1279 return NT_STATUS_OK;
1282 struct smbd_smb2_request_pending_state {
1283 struct smbd_server_connection *sconn;
1284 struct smbd_smb2_send_queue queue_entry;
1285 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1286 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1289 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1290 struct tevent_timer *te,
1291 struct timeval current_time,
1292 void *private_data);
1294 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1295 struct tevent_req *subreq,
1296 uint32_t defer_time)
1298 NTSTATUS status;
1299 struct timeval defer_endtime;
1300 uint8_t *outhdr = NULL;
1301 uint32_t flags;
1303 if (!tevent_req_is_in_progress(subreq)) {
1305 * This is a performance optimization,
1306 * it avoids one tevent_loop iteration,
1307 * which means we avoid one
1308 * talloc_stackframe_pool/talloc_free pair.
1310 tevent_req_notify_callback(subreq);
1311 return NT_STATUS_OK;
1314 req->subreq = subreq;
1315 subreq = NULL;
1317 if (req->async_te) {
1318 /* We're already async. */
1319 return NT_STATUS_OK;
1322 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1323 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1324 if (flags & SMB2_HDR_FLAG_ASYNC) {
1325 /* We're already async. */
1326 return NT_STATUS_OK;
1329 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1331 * We're trying to go async in a compound
1332 * request chain.
1333 * This is only allowed for opens that
1334 * cause an oplock break, otherwise it
1335 * is not allowed. See [MS-SMB2].pdf
1336 * note <194> on Section 3.3.5.2.7.
1338 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1340 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1342 * Cancel the outstanding request.
1344 bool ok = tevent_req_cancel(req->subreq);
1345 if (ok) {
1346 return NT_STATUS_OK;
1348 TALLOC_FREE(req->subreq);
1349 return smbd_smb2_request_error(req,
1350 NT_STATUS_INTERNAL_ERROR);
1354 if (DEBUGLEVEL >= 10) {
1355 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1356 (unsigned int)req->current_idx );
1357 print_req_vectors(req);
1360 if (req->current_idx > 1) {
1362 * We're going async in a compound
1363 * chain after the first request has
1364 * already been processed. Send an
1365 * interim response containing the
1366 * set of replies already generated.
1368 int idx = req->current_idx;
1370 status = smb2_send_async_interim_response(req);
1371 if (!NT_STATUS_IS_OK(status)) {
1372 return status;
1374 if (req->first_key.length > 0) {
1375 data_blob_clear_free(&req->first_key);
1378 req->current_idx = 1;
1381 * Re-arrange the in.vectors to remove what
1382 * we just sent.
1384 memmove(&req->in.vector[1],
1385 &req->in.vector[idx],
1386 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1387 req->in.vector_count = 1 + (req->in.vector_count - idx);
1389 /* Re-arrange the out.vectors to match. */
1390 memmove(&req->out.vector[1],
1391 &req->out.vector[idx],
1392 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1393 req->out.vector_count = 1 + (req->out.vector_count - idx);
1395 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1397 * We only have one remaining request as
1398 * we've processed everything else.
1399 * This is no longer a compound request.
1401 req->compound_related = false;
1402 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1403 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1404 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1407 if (req->last_key.length > 0) {
1408 data_blob_clear_free(&req->last_key);
1411 defer_endtime = timeval_current_ofs_usec(defer_time);
1412 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1413 req, defer_endtime,
1414 smbd_smb2_request_pending_timer,
1415 req);
1416 if (req->async_te == NULL) {
1417 return NT_STATUS_NO_MEMORY;
1420 return NT_STATUS_OK;
1423 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1424 struct tevent_timer *te,
1425 struct timeval current_time,
1426 void *private_data)
1428 struct smbd_smb2_request *req =
1429 talloc_get_type_abort(private_data,
1430 struct smbd_smb2_request);
1431 struct smbd_server_connection *sconn = req->sconn;
1432 struct smbXsrv_connection *xconn = sconn->conn;
1433 struct smbd_smb2_request_pending_state *state = NULL;
1434 uint8_t *outhdr = NULL;
1435 const uint8_t *inhdr = NULL;
1436 uint8_t *tf = NULL;
1437 size_t tf_len = 0;
1438 uint8_t *hdr = NULL;
1439 uint8_t *body = NULL;
1440 uint8_t *dyn = NULL;
1441 uint32_t flags = 0;
1442 uint64_t session_id = 0;
1443 uint64_t message_id = 0;
1444 uint64_t nonce_high = 0;
1445 uint64_t nonce_low = 0;
1446 uint64_t async_id = 0;
1447 NTSTATUS status;
1449 TALLOC_FREE(req->async_te);
1451 /* Ensure our final reply matches the interim one. */
1452 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1453 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1454 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1455 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1456 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1458 async_id = message_id; /* keep it simple for now... */
1460 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1461 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1463 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1464 "going async\n",
1465 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1466 (unsigned long long)async_id ));
1469 * What we send is identical to a smbd_smb2_request_error
1470 * packet with an error status of STATUS_PENDING. Make use
1471 * of this fact sometime when refactoring. JRA.
1474 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1475 if (state == NULL) {
1476 smbd_server_connection_terminate(req->sconn,
1477 nt_errstr(NT_STATUS_NO_MEMORY));
1478 return;
1480 state->sconn = req->sconn;
1482 tf = state->buf + NBT_HDR_SIZE;
1483 tf_len = SMB2_TF_HDR_SIZE;
1485 hdr = tf + SMB2_TF_HDR_SIZE;
1486 body = hdr + SMB2_HDR_BODY;
1487 dyn = body + 8;
1489 if (req->do_encryption) {
1490 struct smbXsrv_session *x = req->session;
1492 nonce_high = x->nonce_high;
1493 nonce_low = x->nonce_low;
1495 x->nonce_low += 1;
1496 if (x->nonce_low == 0) {
1497 x->nonce_low += 1;
1498 x->nonce_high += 1;
1502 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1503 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1504 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1505 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1507 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1508 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1509 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1510 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1511 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1513 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1514 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1515 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1516 SBVAL(hdr, SMB2_HDR_PID, async_id);
1517 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1518 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1519 memcpy(hdr+SMB2_HDR_SIGNATURE,
1520 outhdr+SMB2_HDR_SIGNATURE, 16);
1522 SSVAL(body, 0x00, 0x08 + 1);
1524 SCVAL(body, 0x02, 0);
1525 SCVAL(body, 0x03, 0);
1526 SIVAL(body, 0x04, 0);
1527 /* Match W2K8R2... */
1528 SCVAL(dyn, 0x00, 0x21);
1530 state->vector[0].iov_base = (void *)state->buf;
1531 state->vector[0].iov_len = NBT_HDR_SIZE;
1533 if (req->do_encryption) {
1534 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1535 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1536 } else {
1537 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1538 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1541 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1542 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1544 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1545 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1547 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1548 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1550 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1552 /* Ensure we correctly go through crediting. Grant
1553 the credits now, and zero credits on the final
1554 response. */
1555 smb2_set_operation_credit(req->xconn,
1556 SMBD_SMB2_IN_HDR_IOV(req),
1557 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1559 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1561 if (DEBUGLVL(10)) {
1562 int i;
1564 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1565 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1566 (unsigned int)i,
1567 (unsigned int)ARRAY_SIZE(state->vector),
1568 (unsigned int)state->vector[i].iov_len);
1572 if (req->do_encryption) {
1573 struct smbXsrv_session *x = req->session;
1574 DATA_BLOB encryption_key = x->global->encryption_key;
1576 status = smb2_signing_encrypt_pdu(encryption_key,
1577 xconn->protocol,
1578 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1579 SMBD_SMB2_NUM_IOV_PER_REQ);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 smbd_server_connection_terminate(req->sconn,
1582 nt_errstr(status));
1583 return;
1585 } else if (req->do_signing) {
1586 struct smbXsrv_session *x = req->session;
1587 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1589 status = smb2_signing_sign_pdu(signing_key,
1590 xconn->protocol,
1591 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1592 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 smbd_server_connection_terminate(req->sconn,
1595 nt_errstr(status));
1596 return;
1600 state->queue_entry.mem_ctx = state;
1601 state->queue_entry.vector = state->vector;
1602 state->queue_entry.count = ARRAY_SIZE(state->vector);
1603 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1604 xconn->smb2.send_queue_len++;
1606 status = smbd_smb2_flush_send_queue(xconn);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 smbd_server_connection_terminate(sconn,
1609 nt_errstr(status));
1610 return;
1614 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1616 struct smbd_server_connection *sconn = req->sconn;
1617 struct smbXsrv_connection *xconn = sconn->conn;
1618 struct smbd_smb2_request *cur;
1619 const uint8_t *inhdr;
1620 uint32_t flags;
1621 uint64_t search_message_id;
1622 uint64_t search_async_id;
1623 uint64_t found_id;
1625 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1627 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1628 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1629 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1632 * we don't need the request anymore
1633 * cancel requests never have a response
1635 DLIST_REMOVE(xconn->smb2.requests, req);
1636 TALLOC_FREE(req);
1638 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1639 const uint8_t *outhdr;
1640 uint64_t message_id;
1641 uint64_t async_id;
1643 if (cur->compound_related) {
1645 * Never cancel anything in a compound request.
1646 * Way too hard to deal with the result.
1648 continue;
1651 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1653 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1654 async_id = BVAL(outhdr, SMB2_HDR_PID);
1656 if (flags & SMB2_HDR_FLAG_ASYNC) {
1657 if (search_async_id == async_id) {
1658 found_id = async_id;
1659 break;
1661 } else {
1662 if (search_message_id == message_id) {
1663 found_id = message_id;
1664 break;
1669 if (cur && cur->subreq) {
1670 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1671 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1672 "cancel opcode[%s] mid %llu\n",
1673 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1674 (unsigned long long)found_id ));
1675 tevent_req_cancel(cur->subreq);
1678 return NT_STATUS_OK;
1681 /*************************************************************
1682 Ensure an incoming tid is a valid one for us to access.
1683 Change to the associated uid credentials and chdir to the
1684 valid tid directory.
1685 *************************************************************/
1687 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1689 const uint8_t *inhdr;
1690 uint32_t in_flags;
1691 uint32_t in_tid;
1692 struct smbXsrv_tcon *tcon;
1693 NTSTATUS status;
1694 NTTIME now = timeval_to_nttime(&req->request_time);
1696 req->tcon = NULL;
1698 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1700 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1701 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1703 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1704 in_tid = req->last_tid;
1707 req->last_tid = 0;
1709 status = smb2srv_tcon_lookup(req->session,
1710 in_tid, now, &tcon);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return status;
1715 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1716 return NT_STATUS_ACCESS_DENIED;
1719 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1720 if (!set_current_service(tcon->compat, 0, true)) {
1721 return NT_STATUS_ACCESS_DENIED;
1724 req->tcon = tcon;
1725 req->last_tid = in_tid;
1727 return NT_STATUS_OK;
1730 /*************************************************************
1731 Ensure an incoming session_id is a valid one for us to access.
1732 *************************************************************/
1734 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1736 const uint8_t *inhdr;
1737 uint32_t in_flags;
1738 uint16_t in_opcode;
1739 uint64_t in_session_id;
1740 struct smbXsrv_session *session = NULL;
1741 struct auth_session_info *session_info;
1742 NTSTATUS status;
1743 NTTIME now = timeval_to_nttime(&req->request_time);
1745 req->session = NULL;
1746 req->tcon = NULL;
1748 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1750 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1751 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1752 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1754 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1755 in_session_id = req->last_session_id;
1758 req->last_session_id = 0;
1760 /* lookup an existing session */
1761 status = smb2srv_session_lookup(req->sconn->conn,
1762 in_session_id, now,
1763 &session);
1764 if (session) {
1765 req->session = session;
1766 req->last_session_id = in_session_id;
1768 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1769 switch (in_opcode) {
1770 case SMB2_OP_SESSSETUP:
1771 status = NT_STATUS_OK;
1772 break;
1773 default:
1774 break;
1777 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1778 switch (in_opcode) {
1779 case SMB2_OP_TCON:
1780 case SMB2_OP_CREATE:
1781 case SMB2_OP_GETINFO:
1782 case SMB2_OP_SETINFO:
1783 return NT_STATUS_INVALID_HANDLE;
1784 default:
1786 * Notice the check for
1787 * (session_info == NULL)
1788 * below.
1790 status = NT_STATUS_OK;
1791 break;
1794 if (!NT_STATUS_IS_OK(status)) {
1795 return status;
1798 session_info = session->global->auth_session_info;
1799 if (session_info == NULL) {
1800 return NT_STATUS_INVALID_HANDLE;
1803 if (in_session_id != req->sconn->conn->last_session_id) {
1804 req->sconn->conn->last_session_id = in_session_id;
1805 set_current_user_info(session_info->unix_info->sanitized_username,
1806 session_info->unix_info->unix_name,
1807 session_info->info->domain_name);
1810 return NT_STATUS_OK;
1813 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1814 uint32_t data_length)
1816 struct smbXsrv_connection *xconn = req->sconn->conn;
1817 uint16_t needed_charge;
1818 uint16_t credit_charge = 1;
1819 const uint8_t *inhdr;
1821 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1823 if (xconn->smb2.credits.multicredit) {
1824 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1825 credit_charge = MAX(credit_charge, 1);
1828 needed_charge = (data_length - 1)/ 65536 + 1;
1830 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1831 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1832 credit_charge, needed_charge));
1834 if (needed_charge > credit_charge) {
1835 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1836 credit_charge, needed_charge));
1837 return NT_STATUS_INVALID_PARAMETER;
1840 return NT_STATUS_OK;
1843 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1844 size_t expected_body_size)
1846 struct iovec *inhdr_v;
1847 const uint8_t *inhdr;
1848 uint16_t opcode;
1849 const uint8_t *inbody;
1850 size_t body_size;
1851 size_t min_dyn_size = expected_body_size & 0x00000001;
1852 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1855 * The following should be checked already.
1857 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1858 return NT_STATUS_INTERNAL_ERROR;
1860 if (req->current_idx > max_idx) {
1861 return NT_STATUS_INTERNAL_ERROR;
1864 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1865 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1866 return NT_STATUS_INTERNAL_ERROR;
1868 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1869 return NT_STATUS_INTERNAL_ERROR;
1872 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1873 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1875 switch (opcode) {
1876 case SMB2_OP_IOCTL:
1877 case SMB2_OP_GETINFO:
1878 min_dyn_size = 0;
1879 break;
1880 case SMB2_OP_WRITE:
1881 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1882 if (req->smb1req->unread_bytes < min_dyn_size) {
1883 return NT_STATUS_INVALID_PARAMETER;
1886 min_dyn_size = 0;
1888 break;
1892 * Now check the expected body size,
1893 * where the last byte might be in the
1894 * dynamic section..
1896 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1897 return NT_STATUS_INVALID_PARAMETER;
1899 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1900 return NT_STATUS_INVALID_PARAMETER;
1903 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1905 body_size = SVAL(inbody, 0x00);
1906 if (body_size != expected_body_size) {
1907 return NT_STATUS_INVALID_PARAMETER;
1910 return NT_STATUS_OK;
1913 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1915 struct smbXsrv_connection *xconn = req->sconn->conn;
1916 const struct smbd_smb2_dispatch_table *call = NULL;
1917 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1918 const uint8_t *inhdr;
1919 uint16_t opcode;
1920 uint32_t flags;
1921 uint64_t mid;
1922 NTSTATUS status;
1923 NTSTATUS session_status;
1924 uint32_t allowed_flags;
1925 NTSTATUS return_value;
1926 struct smbXsrv_session *x = NULL;
1927 bool signing_required = false;
1928 bool encryption_required = false;
1930 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1932 /* TODO: verify more things */
1934 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1935 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1936 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1937 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1938 smb2_opcode_name(opcode),
1939 (unsigned long long)mid));
1941 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1943 * once the protocol is negotiated
1944 * SMB2_OP_NEGPROT is not allowed anymore
1946 if (opcode == SMB2_OP_NEGPROT) {
1947 /* drop the connection */
1948 return NT_STATUS_INVALID_PARAMETER;
1950 } else {
1952 * if the protocol is not negotiated yet
1953 * only SMB2_OP_NEGPROT is allowed.
1955 if (opcode != SMB2_OP_NEGPROT) {
1956 /* drop the connection */
1957 return NT_STATUS_INVALID_PARAMETER;
1962 * Check if the client provided a valid session id,
1963 * if so smbd_smb2_request_check_session() calls
1964 * set_current_user_info().
1966 * As some command don't require a valid session id
1967 * we defer the check of the session_status
1969 session_status = smbd_smb2_request_check_session(req);
1970 x = req->session;
1971 if (x != NULL) {
1972 signing_required = x->global->signing_required;
1973 encryption_required = x->global->encryption_required;
1975 if (opcode == SMB2_OP_SESSSETUP &&
1976 x->global->channels[0].signing_key.length) {
1977 signing_required = true;
1981 req->do_signing = false;
1982 req->do_encryption = false;
1983 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1984 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1985 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1987 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1988 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1989 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1990 (unsigned long long)x->global->session_wire_id,
1991 (unsigned long long)tf_session_id));
1993 * TODO: windows allows this...
1994 * should we drop the connection?
1996 * For now we just return ACCESS_DENIED
1997 * (Windows clients never trigger this)
1998 * and wait for an update of [MS-SMB2].
2000 return smbd_smb2_request_error(req,
2001 NT_STATUS_ACCESS_DENIED);
2004 req->do_encryption = true;
2007 if (encryption_required && !req->do_encryption) {
2008 return smbd_smb2_request_error(req,
2009 NT_STATUS_ACCESS_DENIED);
2012 call = smbd_smb2_call(opcode);
2013 if (call == NULL) {
2014 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2017 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2018 SMB2_HDR_FLAG_SIGNED |
2019 SMB2_HDR_FLAG_DFS;
2020 if (opcode == SMB2_OP_CANCEL) {
2021 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2023 if ((flags & ~allowed_flags) != 0) {
2024 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2027 if (flags & SMB2_HDR_FLAG_CHAINED) {
2029 * This check is mostly for giving the correct error code
2030 * for compounded requests.
2032 if (!NT_STATUS_IS_OK(session_status)) {
2033 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2035 } else {
2036 req->compat_chain_fsp = NULL;
2039 if (req->do_encryption) {
2040 signing_required = false;
2041 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2042 DATA_BLOB signing_key;
2044 if (x == NULL) {
2046 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2047 * If the SMB2 header of the SMB2 NEGOTIATE
2048 * request has the SMB2_FLAGS_SIGNED bit set in the
2049 * Flags field, the server MUST fail the request
2050 * with STATUS_INVALID_PARAMETER.
2052 * Microsoft test tool checks this.
2055 if ((opcode == SMB2_OP_NEGPROT) &&
2056 (flags & SMB2_HDR_FLAG_SIGNED)) {
2057 status = NT_STATUS_INVALID_PARAMETER;
2058 } else {
2059 status = NT_STATUS_USER_SESSION_DELETED;
2061 return smbd_smb2_request_error(req, status);
2064 signing_key = x->global->channels[0].signing_key;
2067 * If we have a signing key, we should
2068 * sign the response
2070 if (signing_key.length > 0) {
2071 req->do_signing = true;
2074 status = smb2_signing_check_pdu(signing_key,
2075 xconn->protocol,
2076 SMBD_SMB2_IN_HDR_IOV(req),
2077 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2078 if (!NT_STATUS_IS_OK(status)) {
2079 return smbd_smb2_request_error(req, status);
2083 * Now that we know the request was correctly signed
2084 * we have to sign the response too.
2086 req->do_signing = true;
2088 if (!NT_STATUS_IS_OK(session_status)) {
2089 return smbd_smb2_request_error(req, session_status);
2091 } else if (opcode == SMB2_OP_CANCEL) {
2092 /* Cancel requests are allowed to skip the signing */
2093 } else if (signing_required) {
2095 * If signing is required we try to sign
2096 * a possible error response
2098 req->do_signing = true;
2099 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2102 if (flags & SMB2_HDR_FLAG_CHAINED) {
2103 req->compound_related = true;
2106 if (call->need_session) {
2107 if (!NT_STATUS_IS_OK(session_status)) {
2108 return smbd_smb2_request_error(req, session_status);
2112 if (call->need_tcon) {
2113 SMB_ASSERT(call->need_session);
2116 * This call needs to be run as user.
2118 * smbd_smb2_request_check_tcon()
2119 * calls change_to_user() on success.
2121 status = smbd_smb2_request_check_tcon(req);
2122 if (!NT_STATUS_IS_OK(status)) {
2123 return smbd_smb2_request_error(req, status);
2125 if (req->tcon->global->encryption_required) {
2126 encryption_required = true;
2128 if (encryption_required && !req->do_encryption) {
2129 return smbd_smb2_request_error(req,
2130 NT_STATUS_ACCESS_DENIED);
2134 if (call->fileid_ofs != 0) {
2135 size_t needed = call->fileid_ofs + 16;
2136 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2137 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2138 uint64_t file_id_persistent;
2139 uint64_t file_id_volatile;
2140 struct files_struct *fsp;
2142 SMB_ASSERT(call->need_tcon);
2144 if (needed > body_size) {
2145 return smbd_smb2_request_error(req,
2146 NT_STATUS_INVALID_PARAMETER);
2149 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2150 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2152 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2153 if (fsp == NULL) {
2154 if (!call->allow_invalid_fileid) {
2155 return smbd_smb2_request_error(req,
2156 NT_STATUS_FILE_CLOSED);
2159 if (file_id_persistent != UINT64_MAX) {
2160 return smbd_smb2_request_error(req,
2161 NT_STATUS_FILE_CLOSED);
2163 if (file_id_volatile != UINT64_MAX) {
2164 return smbd_smb2_request_error(req,
2165 NT_STATUS_FILE_CLOSED);
2170 if (call->as_root) {
2171 SMB_ASSERT(call->fileid_ofs == 0);
2172 /* This call needs to be run as root */
2173 change_to_root_user();
2174 } else {
2175 SMB_ASSERT(call->need_tcon);
2178 switch (opcode) {
2179 case SMB2_OP_NEGPROT:
2181 START_PROFILE(smb2_negprot);
2182 return_value = smbd_smb2_request_process_negprot(req);
2183 END_PROFILE(smb2_negprot);
2185 break;
2187 case SMB2_OP_SESSSETUP:
2189 START_PROFILE(smb2_sesssetup);
2190 return_value = smbd_smb2_request_process_sesssetup(req);
2191 END_PROFILE(smb2_sesssetup);
2193 break;
2195 case SMB2_OP_LOGOFF:
2197 START_PROFILE(smb2_logoff);
2198 return_value = smbd_smb2_request_process_logoff(req);
2199 END_PROFILE(smb2_logoff);
2201 break;
2203 case SMB2_OP_TCON:
2205 START_PROFILE(smb2_tcon);
2206 return_value = smbd_smb2_request_process_tcon(req);
2207 END_PROFILE(smb2_tcon);
2209 break;
2211 case SMB2_OP_TDIS:
2213 START_PROFILE(smb2_tdis);
2214 return_value = smbd_smb2_request_process_tdis(req);
2215 END_PROFILE(smb2_tdis);
2217 break;
2219 case SMB2_OP_CREATE:
2221 START_PROFILE(smb2_create);
2222 return_value = smbd_smb2_request_process_create(req);
2223 END_PROFILE(smb2_create);
2225 break;
2227 case SMB2_OP_CLOSE:
2229 START_PROFILE(smb2_close);
2230 return_value = smbd_smb2_request_process_close(req);
2231 END_PROFILE(smb2_close);
2233 break;
2235 case SMB2_OP_FLUSH:
2237 START_PROFILE(smb2_flush);
2238 return_value = smbd_smb2_request_process_flush(req);
2239 END_PROFILE(smb2_flush);
2241 break;
2243 case SMB2_OP_READ:
2245 START_PROFILE(smb2_read);
2246 return_value = smbd_smb2_request_process_read(req);
2247 END_PROFILE(smb2_read);
2249 break;
2251 case SMB2_OP_WRITE:
2253 START_PROFILE(smb2_write);
2254 return_value = smbd_smb2_request_process_write(req);
2255 END_PROFILE(smb2_write);
2257 break;
2259 case SMB2_OP_LOCK:
2261 START_PROFILE(smb2_lock);
2262 return_value = smbd_smb2_request_process_lock(req);
2263 END_PROFILE(smb2_lock);
2265 break;
2267 case SMB2_OP_IOCTL:
2269 START_PROFILE(smb2_ioctl);
2270 return_value = smbd_smb2_request_process_ioctl(req);
2271 END_PROFILE(smb2_ioctl);
2273 break;
2275 case SMB2_OP_CANCEL:
2277 START_PROFILE(smb2_cancel);
2278 return_value = smbd_smb2_request_process_cancel(req);
2279 END_PROFILE(smb2_cancel);
2281 break;
2283 case SMB2_OP_KEEPALIVE:
2285 START_PROFILE(smb2_keepalive);
2286 return_value = smbd_smb2_request_process_keepalive(req);
2287 END_PROFILE(smb2_keepalive);
2289 break;
2291 case SMB2_OP_FIND:
2293 START_PROFILE(smb2_find);
2294 return_value = smbd_smb2_request_process_find(req);
2295 END_PROFILE(smb2_find);
2297 break;
2299 case SMB2_OP_NOTIFY:
2301 START_PROFILE(smb2_notify);
2302 return_value = smbd_smb2_request_process_notify(req);
2303 END_PROFILE(smb2_notify);
2305 break;
2307 case SMB2_OP_GETINFO:
2309 START_PROFILE(smb2_getinfo);
2310 return_value = smbd_smb2_request_process_getinfo(req);
2311 END_PROFILE(smb2_getinfo);
2313 break;
2315 case SMB2_OP_SETINFO:
2317 START_PROFILE(smb2_setinfo);
2318 return_value = smbd_smb2_request_process_setinfo(req);
2319 END_PROFILE(smb2_setinfo);
2321 break;
2323 case SMB2_OP_BREAK:
2325 START_PROFILE(smb2_break);
2326 return_value = smbd_smb2_request_process_break(req);
2327 END_PROFILE(smb2_break);
2329 break;
2331 default:
2332 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2333 break;
2335 return return_value;
2338 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2340 struct smbXsrv_connection *xconn = req->xconn;
2341 int first_idx = 1;
2342 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2343 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2344 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2345 NTSTATUS status;
2347 req->subreq = NULL;
2348 TALLOC_FREE(req->async_te);
2350 if (req->do_encryption &&
2351 (firsttf->iov_len == 0) &&
2352 (req->first_key.length == 0) &&
2353 (req->session != NULL) &&
2354 (req->session->global->encryption_key.length != 0))
2356 DATA_BLOB encryption_key = req->session->global->encryption_key;
2357 uint8_t *tf;
2358 uint64_t session_id = req->session->global->session_wire_id;
2359 struct smbXsrv_session *x = req->session;
2360 uint64_t nonce_high;
2361 uint64_t nonce_low;
2363 nonce_high = x->nonce_high;
2364 nonce_low = x->nonce_low;
2366 x->nonce_low += 1;
2367 if (x->nonce_low == 0) {
2368 x->nonce_low += 1;
2369 x->nonce_high += 1;
2373 * We need to place the SMB2_TRANSFORM header before the
2374 * first SMB2 header
2378 * we need to remember the encryption key
2379 * and defer the signing/encryption until
2380 * we are sure that we do not change
2381 * the header again.
2383 req->first_key = data_blob_dup_talloc(req, encryption_key);
2384 if (req->first_key.data == NULL) {
2385 return NT_STATUS_NO_MEMORY;
2388 tf = talloc_zero_array(req, uint8_t,
2389 SMB2_TF_HDR_SIZE);
2390 if (tf == NULL) {
2391 return NT_STATUS_NO_MEMORY;
2394 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2395 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2396 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2397 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2399 firsttf->iov_base = (void *)tf;
2400 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2403 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2404 (req->last_key.length > 0) &&
2405 (firsttf->iov_len == 0))
2407 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2408 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2411 * As we are sure the header of the last request in the
2412 * compound chain will not change, we can to sign here
2413 * with the last signing key we remembered.
2415 status = smb2_signing_sign_pdu(req->last_key,
2416 xconn->protocol,
2417 lasthdr,
2418 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2419 if (!NT_STATUS_IS_OK(status)) {
2420 return status;
2423 if (req->last_key.length > 0) {
2424 data_blob_clear_free(&req->last_key);
2427 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2429 if (req->current_idx < req->out.vector_count) {
2431 * We must process the remaining compound
2432 * SMB2 requests before any new incoming SMB2
2433 * requests. This is because incoming SMB2
2434 * requests may include a cancel for a
2435 * compound request we haven't processed
2436 * yet.
2438 struct tevent_immediate *im = tevent_create_immediate(req);
2439 if (!im) {
2440 return NT_STATUS_NO_MEMORY;
2443 if (req->do_signing && firsttf->iov_len == 0) {
2444 struct smbXsrv_session *x = req->session;
2445 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2448 * we need to remember the signing key
2449 * and defer the signing until
2450 * we are sure that we do not change
2451 * the header again.
2453 req->last_key = data_blob_dup_talloc(req, signing_key);
2454 if (req->last_key.data == NULL) {
2455 return NT_STATUS_NO_MEMORY;
2459 tevent_schedule_immediate(im,
2460 req->sconn->ev_ctx,
2461 smbd_smb2_request_dispatch_immediate,
2462 req);
2463 return NT_STATUS_OK;
2466 if (req->compound_related) {
2467 req->compound_related = false;
2470 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2472 /* Set credit for these operations (zero credits if this
2473 is a final reply for an async operation). */
2474 smb2_calculate_credits(req, req);
2477 * now check if we need to sign the current response
2479 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2480 status = smb2_signing_encrypt_pdu(req->first_key,
2481 xconn->protocol,
2482 firsttf,
2483 req->out.vector_count - first_idx);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 return status;
2487 } else if (req->do_signing) {
2488 struct smbXsrv_session *x = req->session;
2489 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2491 status = smb2_signing_sign_pdu(signing_key,
2492 xconn->protocol,
2493 outhdr,
2494 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2495 if (!NT_STATUS_IS_OK(status)) {
2496 return status;
2499 if (req->first_key.length > 0) {
2500 data_blob_clear_free(&req->first_key);
2503 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2504 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2505 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2506 /* Dynamic part is NULL. Chop it off,
2507 We're going to send it via sendfile. */
2508 req->out.vector_count -= 1;
2512 * We're done with this request -
2513 * move it off the "being processed" queue.
2515 DLIST_REMOVE(xconn->smb2.requests, req);
2517 req->queue_entry.mem_ctx = req;
2518 req->queue_entry.vector = req->out.vector;
2519 req->queue_entry.count = req->out.vector_count;
2520 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2521 xconn->smb2.send_queue_len++;
2523 status = smbd_smb2_flush_send_queue(xconn);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 return status;
2528 return NT_STATUS_OK;
2531 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2533 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2534 struct tevent_immediate *im,
2535 void *private_data)
2537 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2538 struct smbd_smb2_request);
2539 struct smbd_server_connection *sconn = req->sconn;
2540 NTSTATUS status;
2542 TALLOC_FREE(im);
2544 if (DEBUGLEVEL >= 10) {
2545 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2546 req->current_idx, req->in.vector_count));
2547 print_req_vectors(req);
2550 status = smbd_smb2_request_dispatch(req);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 smbd_server_connection_terminate(sconn, nt_errstr(status));
2553 return;
2556 status = smbd_smb2_request_next_incoming(sconn);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 smbd_server_connection_terminate(sconn, nt_errstr(status));
2559 return;
2563 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2564 NTSTATUS status,
2565 DATA_BLOB body, DATA_BLOB *dyn,
2566 const char *location)
2568 uint8_t *outhdr;
2569 struct iovec *outbody_v;
2570 struct iovec *outdyn_v;
2571 uint32_t next_command_ofs;
2573 DEBUG(10,("smbd_smb2_request_done_ex: "
2574 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2575 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2576 dyn ? "yes": "no",
2577 (unsigned int)(dyn ? dyn->length : 0),
2578 location));
2580 if (body.length < 2) {
2581 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2584 if ((body.length % 2) != 0) {
2585 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2588 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2589 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2590 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2592 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2593 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2595 outbody_v->iov_base = (void *)body.data;
2596 outbody_v->iov_len = body.length;
2598 if (dyn) {
2599 outdyn_v->iov_base = (void *)dyn->data;
2600 outdyn_v->iov_len = dyn->length;
2601 } else {
2602 outdyn_v->iov_base = NULL;
2603 outdyn_v->iov_len = 0;
2606 /* see if we need to recalculate the offset to the next response */
2607 if (next_command_ofs > 0) {
2608 next_command_ofs = SMB2_HDR_BODY;
2609 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2610 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2613 if ((next_command_ofs % 8) != 0) {
2614 size_t pad_size = 8 - (next_command_ofs % 8);
2615 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2617 * if the dyn buffer is empty
2618 * we can use it to add padding
2620 uint8_t *pad;
2622 pad = talloc_zero_array(req,
2623 uint8_t, pad_size);
2624 if (pad == NULL) {
2625 return smbd_smb2_request_error(req,
2626 NT_STATUS_NO_MEMORY);
2629 outdyn_v->iov_base = (void *)pad;
2630 outdyn_v->iov_len = pad_size;
2631 } else {
2633 * For now we copy the dynamic buffer
2634 * and add the padding to the new buffer
2636 size_t old_size;
2637 uint8_t *old_dyn;
2638 size_t new_size;
2639 uint8_t *new_dyn;
2641 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2642 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2644 new_size = old_size + pad_size;
2645 new_dyn = talloc_zero_array(req,
2646 uint8_t, new_size);
2647 if (new_dyn == NULL) {
2648 return smbd_smb2_request_error(req,
2649 NT_STATUS_NO_MEMORY);
2652 memcpy(new_dyn, old_dyn, old_size);
2653 memset(new_dyn + old_size, 0, pad_size);
2655 outdyn_v->iov_base = (void *)new_dyn;
2656 outdyn_v->iov_len = new_size;
2658 next_command_ofs += pad_size;
2661 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2663 return smbd_smb2_request_reply(req);
2666 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2667 NTSTATUS status,
2668 DATA_BLOB *info,
2669 const char *location)
2671 struct smbXsrv_connection *xconn = req->sconn->conn;
2672 DATA_BLOB body;
2673 DATA_BLOB _dyn;
2674 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2675 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2677 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2678 req->current_idx, nt_errstr(status), info ? " +info" : "",
2679 location));
2681 if (unread_bytes) {
2682 /* Recvfile error. Drain incoming socket. */
2683 size_t ret;
2685 errno = 0;
2686 ret = drain_socket(xconn->transport.sock, unread_bytes);
2687 if (ret != unread_bytes) {
2688 NTSTATUS error;
2690 if (errno == 0) {
2691 error = NT_STATUS_IO_DEVICE_ERROR;
2692 } else {
2693 error = map_nt_error_from_unix_common(errno);
2696 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2697 "ret[%u] errno[%d] => %s\n",
2698 (unsigned)unread_bytes,
2699 (unsigned)ret, errno, nt_errstr(error)));
2700 return error;
2704 body.data = outhdr + SMB2_HDR_BODY;
2705 body.length = 8;
2706 SSVAL(body.data, 0, 9);
2708 if (info) {
2709 SIVAL(body.data, 0x04, info->length);
2710 } else {
2711 /* Allocated size of req->out.vector[i].iov_base
2712 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2713 * 1 byte without having to do an alloc.
2715 info = &_dyn;
2716 info->data = ((uint8_t *)outhdr) +
2717 OUTVEC_ALLOC_SIZE - 1;
2718 info->length = 1;
2719 SCVAL(info->data, 0, 0);
2723 * Note: Even if there is an error, continue to process the request.
2724 * per MS-SMB2.
2727 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2731 struct smbd_smb2_send_break_state {
2732 struct smbd_server_connection *sconn;
2733 struct smbd_smb2_send_queue queue_entry;
2734 uint8_t nbt_hdr[NBT_HDR_SIZE];
2735 uint8_t tf[SMB2_TF_HDR_SIZE];
2736 uint8_t hdr[SMB2_HDR_BODY];
2737 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2738 uint8_t body[1];
2741 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2742 struct smbXsrv_session *session,
2743 struct smbXsrv_tcon *tcon,
2744 const uint8_t *body,
2745 size_t body_len)
2747 struct smbd_smb2_send_break_state *state;
2748 struct smbXsrv_connection *xconn = sconn->conn;
2749 bool do_encryption = session->global->encryption_required;
2750 uint64_t nonce_high = 0;
2751 uint64_t nonce_low = 0;
2752 NTSTATUS status;
2753 size_t statelen;
2755 if (tcon->global->encryption_required) {
2756 do_encryption = true;
2759 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2760 body_len;
2762 state = talloc_zero_size(sconn, statelen);
2763 if (state == NULL) {
2764 return NT_STATUS_NO_MEMORY;
2766 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2767 state->sconn = sconn;
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(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2781 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2782 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2783 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2785 SIVAL(state->hdr, 0, SMB2_MAGIC);
2786 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2787 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2788 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2789 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2790 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2791 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2792 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2793 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2794 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2795 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2796 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2797 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2799 state->vector[0] = (struct iovec) {
2800 .iov_base = state->nbt_hdr,
2801 .iov_len = sizeof(state->nbt_hdr)
2804 if (do_encryption) {
2805 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2806 .iov_base = state->tf,
2807 .iov_len = sizeof(state->tf)
2809 } else {
2810 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2811 .iov_base = NULL,
2812 .iov_len = 0
2816 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2817 .iov_base = state->hdr,
2818 .iov_len = sizeof(state->hdr)
2821 memcpy(state->body, body, body_len);
2823 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2824 .iov_base = state->body,
2825 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2829 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2832 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2834 if (do_encryption) {
2835 DATA_BLOB encryption_key = session->global->encryption_key;
2837 status = smb2_signing_encrypt_pdu(encryption_key,
2838 xconn->protocol,
2839 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2840 SMBD_SMB2_NUM_IOV_PER_REQ);
2841 if (!NT_STATUS_IS_OK(status)) {
2842 return status;
2846 state->queue_entry.mem_ctx = state;
2847 state->queue_entry.vector = state->vector;
2848 state->queue_entry.count = ARRAY_SIZE(state->vector);
2849 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2850 xconn->smb2.send_queue_len++;
2852 status = smbd_smb2_flush_send_queue(xconn);
2853 if (!NT_STATUS_IS_OK(status)) {
2854 return status;
2857 return NT_STATUS_OK;
2860 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2861 struct smbXsrv_session *session,
2862 struct smbXsrv_tcon *tcon,
2863 struct smbXsrv_open *op,
2864 uint8_t oplock_level)
2866 uint8_t body[0x18];
2868 SSVAL(body, 0x00, sizeof(body));
2869 SCVAL(body, 0x02, oplock_level);
2870 SCVAL(body, 0x03, 0); /* reserved */
2871 SIVAL(body, 0x04, 0); /* reserved */
2872 SBVAL(body, 0x08, op->global->open_persistent_id);
2873 SBVAL(body, 0x10, op->global->open_volatile_id);
2875 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2878 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2880 NTSTATUS status;
2881 uint32_t flags;
2882 uint64_t file_id_persistent;
2883 uint64_t file_id_volatile;
2884 struct smbXsrv_open *op = NULL;
2885 struct files_struct *fsp = NULL;
2886 const uint8_t *body = NULL;
2889 * This is only called with a pktbuf
2890 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2891 * bytes
2894 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2895 /* Transform header. Cannot recvfile. */
2896 return false;
2898 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2899 /* Not SMB2. Normal error path will cope. */
2900 return false;
2902 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2903 /* Not SMB2. Normal error path will cope. */
2904 return false;
2906 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2907 /* Needs to be a WRITE. */
2908 return false;
2910 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2911 /* Chained. Cannot recvfile. */
2912 return false;
2914 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2915 if (flags & SMB2_HDR_FLAG_CHAINED) {
2916 /* Chained. Cannot recvfile. */
2917 return false;
2919 if (flags & SMB2_HDR_FLAG_SIGNED) {
2920 /* Signed. Cannot recvfile. */
2921 return false;
2924 body = &state->pktbuf[SMB2_HDR_BODY];
2926 file_id_persistent = BVAL(body, 0x10);
2927 file_id_volatile = BVAL(body, 0x18);
2929 status = smb2srv_open_lookup(state->req->sconn->conn,
2930 file_id_persistent,
2931 file_id_volatile,
2932 0, /* now */
2933 &op);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 return false;
2938 fsp = op->compat;
2939 if (fsp == NULL) {
2940 return false;
2942 if (fsp->conn == NULL) {
2943 return false;
2946 if (IS_IPC(fsp->conn)) {
2947 return false;
2949 if (IS_PRINT(fsp->conn)) {
2950 return false;
2953 DEBUG(10,("Doing recvfile write len = %u\n",
2954 (unsigned int)(state->pktfull - state->pktlen)));
2956 return true;
2959 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2961 struct smbXsrv_connection *xconn = sconn->conn;
2962 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2963 size_t max_send_queue_len;
2964 size_t cur_send_queue_len;
2966 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2968 * we're not supposed to do any io
2970 return NT_STATUS_OK;
2973 if (state->req != NULL) {
2975 * if there is already a tstream_readv_pdu
2976 * pending, we are done.
2978 return NT_STATUS_OK;
2981 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2982 cur_send_queue_len = xconn->smb2.send_queue_len;
2984 if (cur_send_queue_len > max_send_queue_len) {
2986 * if we have a lot of requests to send,
2987 * we wait until they are on the wire until we
2988 * ask for the next request.
2990 return NT_STATUS_OK;
2993 /* ask for the next request */
2994 ZERO_STRUCTP(state);
2995 state->req = smbd_smb2_request_allocate(xconn);
2996 if (state->req == NULL) {
2997 return NT_STATUS_NO_MEMORY;
2999 state->req->sconn = sconn;
3000 state->req->xconn = xconn;
3001 state->min_recv_size = lp_min_receive_file_size();
3003 TEVENT_FD_READABLE(xconn->transport.fde);
3005 return NT_STATUS_OK;
3008 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3009 uint8_t *inbuf, size_t size)
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(sconn);
3018 if (!NT_STATUS_IS_OK(status)) {
3019 smbd_server_connection_terminate(sconn, nt_errstr(status));
3020 return;
3023 status = smbd_smb2_request_create(sconn, 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(sconn);
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(sconn);
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;