s3:smb2_server: pass smbXsrv_connection to smbd_initialize_smb2()
[Samba.git] / source3 / smbd / smb2_server.c
blobaf2330d7d0058a42c6363371ccc5bea10634a465
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 smbd_server_connection *sconn,
509 uint8_t *inbuf, size_t size,
510 struct smbd_smb2_request **_req)
512 struct smbXsrv_connection *xconn = sconn->conn;
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(sconn->conn,
562 now,
563 inbuf + NBT_HDR_SIZE,
564 size - NBT_HDR_SIZE,
565 req, &req->in.vector,
566 &req->in.vector_count);
567 if (!NT_STATUS_IS_OK(status)) {
568 TALLOC_FREE(req);
569 return status;
572 req->current_idx = 1;
574 *_req = req;
575 return NT_STATUS_OK;
578 static bool smb2_validate_sequence_number(struct 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 smbd_server_connection *sconn);
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 NTSTATUS status;
2540 TALLOC_FREE(im);
2542 if (DEBUGLEVEL >= 10) {
2543 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2544 req->current_idx, req->in.vector_count));
2545 print_req_vectors(req);
2548 status = smbd_smb2_request_dispatch(req);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 smbd_server_connection_terminate(sconn, nt_errstr(status));
2551 return;
2554 status = smbd_smb2_request_next_incoming(sconn);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 smbd_server_connection_terminate(sconn, nt_errstr(status));
2557 return;
2561 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2562 NTSTATUS status,
2563 DATA_BLOB body, DATA_BLOB *dyn,
2564 const char *location)
2566 uint8_t *outhdr;
2567 struct iovec *outbody_v;
2568 struct iovec *outdyn_v;
2569 uint32_t next_command_ofs;
2571 DEBUG(10,("smbd_smb2_request_done_ex: "
2572 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2573 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2574 dyn ? "yes": "no",
2575 (unsigned int)(dyn ? dyn->length : 0),
2576 location));
2578 if (body.length < 2) {
2579 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2582 if ((body.length % 2) != 0) {
2583 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2586 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2587 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2588 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2590 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2591 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2593 outbody_v->iov_base = (void *)body.data;
2594 outbody_v->iov_len = body.length;
2596 if (dyn) {
2597 outdyn_v->iov_base = (void *)dyn->data;
2598 outdyn_v->iov_len = dyn->length;
2599 } else {
2600 outdyn_v->iov_base = NULL;
2601 outdyn_v->iov_len = 0;
2604 /* see if we need to recalculate the offset to the next response */
2605 if (next_command_ofs > 0) {
2606 next_command_ofs = SMB2_HDR_BODY;
2607 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2608 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2611 if ((next_command_ofs % 8) != 0) {
2612 size_t pad_size = 8 - (next_command_ofs % 8);
2613 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2615 * if the dyn buffer is empty
2616 * we can use it to add padding
2618 uint8_t *pad;
2620 pad = talloc_zero_array(req,
2621 uint8_t, pad_size);
2622 if (pad == NULL) {
2623 return smbd_smb2_request_error(req,
2624 NT_STATUS_NO_MEMORY);
2627 outdyn_v->iov_base = (void *)pad;
2628 outdyn_v->iov_len = pad_size;
2629 } else {
2631 * For now we copy the dynamic buffer
2632 * and add the padding to the new buffer
2634 size_t old_size;
2635 uint8_t *old_dyn;
2636 size_t new_size;
2637 uint8_t *new_dyn;
2639 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2640 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2642 new_size = old_size + pad_size;
2643 new_dyn = talloc_zero_array(req,
2644 uint8_t, new_size);
2645 if (new_dyn == NULL) {
2646 return smbd_smb2_request_error(req,
2647 NT_STATUS_NO_MEMORY);
2650 memcpy(new_dyn, old_dyn, old_size);
2651 memset(new_dyn + old_size, 0, pad_size);
2653 outdyn_v->iov_base = (void *)new_dyn;
2654 outdyn_v->iov_len = new_size;
2656 next_command_ofs += pad_size;
2659 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2661 return smbd_smb2_request_reply(req);
2664 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2665 NTSTATUS status,
2666 DATA_BLOB *info,
2667 const char *location)
2669 struct smbXsrv_connection *xconn = req->sconn->conn;
2670 DATA_BLOB body;
2671 DATA_BLOB _dyn;
2672 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2673 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2675 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2676 req->current_idx, nt_errstr(status), info ? " +info" : "",
2677 location));
2679 if (unread_bytes) {
2680 /* Recvfile error. Drain incoming socket. */
2681 size_t ret;
2683 errno = 0;
2684 ret = drain_socket(xconn->transport.sock, unread_bytes);
2685 if (ret != unread_bytes) {
2686 NTSTATUS error;
2688 if (errno == 0) {
2689 error = NT_STATUS_IO_DEVICE_ERROR;
2690 } else {
2691 error = map_nt_error_from_unix_common(errno);
2694 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2695 "ret[%u] errno[%d] => %s\n",
2696 (unsigned)unread_bytes,
2697 (unsigned)ret, errno, nt_errstr(error)));
2698 return error;
2702 body.data = outhdr + SMB2_HDR_BODY;
2703 body.length = 8;
2704 SSVAL(body.data, 0, 9);
2706 if (info) {
2707 SIVAL(body.data, 0x04, info->length);
2708 } else {
2709 /* Allocated size of req->out.vector[i].iov_base
2710 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2711 * 1 byte without having to do an alloc.
2713 info = &_dyn;
2714 info->data = ((uint8_t *)outhdr) +
2715 OUTVEC_ALLOC_SIZE - 1;
2716 info->length = 1;
2717 SCVAL(info->data, 0, 0);
2721 * Note: Even if there is an error, continue to process the request.
2722 * per MS-SMB2.
2725 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2729 struct smbd_smb2_send_break_state {
2730 struct smbd_server_connection *sconn;
2731 struct smbd_smb2_send_queue queue_entry;
2732 uint8_t nbt_hdr[NBT_HDR_SIZE];
2733 uint8_t tf[SMB2_TF_HDR_SIZE];
2734 uint8_t hdr[SMB2_HDR_BODY];
2735 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2736 uint8_t body[1];
2739 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2740 struct smbXsrv_session *session,
2741 struct smbXsrv_tcon *tcon,
2742 const uint8_t *body,
2743 size_t body_len)
2745 struct smbd_smb2_send_break_state *state;
2746 struct smbXsrv_connection *xconn = sconn->conn;
2747 bool do_encryption = session->global->encryption_required;
2748 uint64_t nonce_high = 0;
2749 uint64_t nonce_low = 0;
2750 NTSTATUS status;
2751 size_t statelen;
2753 if (tcon->global->encryption_required) {
2754 do_encryption = true;
2757 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2758 body_len;
2760 state = talloc_zero_size(sconn, statelen);
2761 if (state == NULL) {
2762 return NT_STATUS_NO_MEMORY;
2764 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2765 state->sconn = sconn;
2767 if (do_encryption) {
2768 nonce_high = session->nonce_high;
2769 nonce_low = session->nonce_low;
2771 session->nonce_low += 1;
2772 if (session->nonce_low == 0) {
2773 session->nonce_low += 1;
2774 session->nonce_high += 1;
2778 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2779 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2780 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2781 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2783 SIVAL(state->hdr, 0, SMB2_MAGIC);
2784 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2785 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2786 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2787 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2788 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2789 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2790 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2791 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2792 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2793 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2794 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2795 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2797 state->vector[0] = (struct iovec) {
2798 .iov_base = state->nbt_hdr,
2799 .iov_len = sizeof(state->nbt_hdr)
2802 if (do_encryption) {
2803 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2804 .iov_base = state->tf,
2805 .iov_len = sizeof(state->tf)
2807 } else {
2808 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2809 .iov_base = NULL,
2810 .iov_len = 0
2814 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2815 .iov_base = state->hdr,
2816 .iov_len = sizeof(state->hdr)
2819 memcpy(state->body, body, body_len);
2821 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2822 .iov_base = state->body,
2823 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2827 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2830 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2832 if (do_encryption) {
2833 DATA_BLOB encryption_key = session->global->encryption_key;
2835 status = smb2_signing_encrypt_pdu(encryption_key,
2836 xconn->protocol,
2837 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2838 SMBD_SMB2_NUM_IOV_PER_REQ);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 return status;
2844 state->queue_entry.mem_ctx = state;
2845 state->queue_entry.vector = state->vector;
2846 state->queue_entry.count = ARRAY_SIZE(state->vector);
2847 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2848 xconn->smb2.send_queue_len++;
2850 status = smbd_smb2_flush_send_queue(xconn);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 return status;
2855 return NT_STATUS_OK;
2858 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2859 struct smbXsrv_session *session,
2860 struct smbXsrv_tcon *tcon,
2861 struct smbXsrv_open *op,
2862 uint8_t oplock_level)
2864 uint8_t body[0x18];
2866 SSVAL(body, 0x00, sizeof(body));
2867 SCVAL(body, 0x02, oplock_level);
2868 SCVAL(body, 0x03, 0); /* reserved */
2869 SIVAL(body, 0x04, 0); /* reserved */
2870 SBVAL(body, 0x08, op->global->open_persistent_id);
2871 SBVAL(body, 0x10, op->global->open_volatile_id);
2873 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2876 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2878 NTSTATUS status;
2879 uint32_t flags;
2880 uint64_t file_id_persistent;
2881 uint64_t file_id_volatile;
2882 struct smbXsrv_open *op = NULL;
2883 struct files_struct *fsp = NULL;
2884 const uint8_t *body = NULL;
2887 * This is only called with a pktbuf
2888 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2889 * bytes
2892 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2893 /* Transform header. Cannot recvfile. */
2894 return false;
2896 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2897 /* Not SMB2. Normal error path will cope. */
2898 return false;
2900 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2901 /* Not SMB2. Normal error path will cope. */
2902 return false;
2904 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2905 /* Needs to be a WRITE. */
2906 return false;
2908 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2909 /* Chained. Cannot recvfile. */
2910 return false;
2912 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2913 if (flags & SMB2_HDR_FLAG_CHAINED) {
2914 /* Chained. Cannot recvfile. */
2915 return false;
2917 if (flags & SMB2_HDR_FLAG_SIGNED) {
2918 /* Signed. Cannot recvfile. */
2919 return false;
2922 body = &state->pktbuf[SMB2_HDR_BODY];
2924 file_id_persistent = BVAL(body, 0x10);
2925 file_id_volatile = BVAL(body, 0x18);
2927 status = smb2srv_open_lookup(state->req->sconn->conn,
2928 file_id_persistent,
2929 file_id_volatile,
2930 0, /* now */
2931 &op);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 return false;
2936 fsp = op->compat;
2937 if (fsp == NULL) {
2938 return false;
2940 if (fsp->conn == NULL) {
2941 return false;
2944 if (IS_IPC(fsp->conn)) {
2945 return false;
2947 if (IS_PRINT(fsp->conn)) {
2948 return false;
2951 DEBUG(10,("Doing recvfile write len = %u\n",
2952 (unsigned int)(state->pktfull - state->pktlen)));
2954 return true;
2957 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2959 struct smbXsrv_connection *xconn = sconn->conn;
2960 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2961 size_t max_send_queue_len;
2962 size_t cur_send_queue_len;
2964 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2966 * we're not supposed to do any io
2968 return NT_STATUS_OK;
2971 if (state->req != NULL) {
2973 * if there is already a tstream_readv_pdu
2974 * pending, we are done.
2976 return NT_STATUS_OK;
2979 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2980 cur_send_queue_len = xconn->smb2.send_queue_len;
2982 if (cur_send_queue_len > max_send_queue_len) {
2984 * if we have a lot of requests to send,
2985 * we wait until they are on the wire until we
2986 * ask for the next request.
2988 return NT_STATUS_OK;
2991 /* ask for the next request */
2992 ZERO_STRUCTP(state);
2993 state->req = smbd_smb2_request_allocate(xconn);
2994 if (state->req == NULL) {
2995 return NT_STATUS_NO_MEMORY;
2997 state->req->sconn = sconn;
2998 state->req->xconn = xconn;
2999 state->min_recv_size = lp_min_receive_file_size();
3001 TEVENT_FD_READABLE(xconn->transport.fde);
3003 return NT_STATUS_OK;
3006 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3007 uint8_t *inbuf, size_t size)
3009 struct smbd_server_connection *sconn = xconn->sconn;
3010 NTSTATUS status;
3011 struct smbd_smb2_request *req = NULL;
3013 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3014 (unsigned int)size));
3016 status = smbd_initialize_smb2(xconn);
3017 if (!NT_STATUS_IS_OK(status)) {
3018 smbd_server_connection_terminate(sconn, nt_errstr(status));
3019 return;
3022 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 smbd_server_connection_terminate(sconn, nt_errstr(status));
3025 return;
3028 status = smbd_smb2_request_validate(req);
3029 if (!NT_STATUS_IS_OK(status)) {
3030 smbd_server_connection_terminate(sconn, nt_errstr(status));
3031 return;
3034 status = smbd_smb2_request_setup_out(req);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 smbd_server_connection_terminate(sconn, nt_errstr(status));
3037 return;
3040 status = smbd_smb2_request_dispatch(req);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 smbd_server_connection_terminate(sconn, nt_errstr(status));
3043 return;
3046 status = smbd_smb2_request_next_incoming(sconn);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 smbd_server_connection_terminate(sconn, nt_errstr(status));
3049 return;
3052 sconn->num_requests++;
3055 static int socket_error_from_errno(int ret,
3056 int sys_errno,
3057 bool *retry)
3059 *retry = false;
3061 if (ret >= 0) {
3062 return 0;
3065 if (ret != -1) {
3066 return EIO;
3069 if (sys_errno == 0) {
3070 return EIO;
3073 if (sys_errno == EINTR) {
3074 *retry = true;
3075 return sys_errno;
3078 if (sys_errno == EINPROGRESS) {
3079 *retry = true;
3080 return sys_errno;
3083 if (sys_errno == EAGAIN) {
3084 *retry = true;
3085 return sys_errno;
3088 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3089 if (sys_errno == ENOMEM) {
3090 *retry = true;
3091 return sys_errno;
3094 #ifdef EWOULDBLOCK
3095 #if EWOULDBLOCK != EAGAIN
3096 if (sys_errno == EWOULDBLOCK) {
3097 *retry = true;
3098 return sys_errno;
3100 #endif
3101 #endif
3103 return sys_errno;
3106 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3108 int ret;
3109 int err;
3110 bool retry;
3112 if (xconn->smb2.send_queue == NULL) {
3113 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3114 return NT_STATUS_OK;
3117 while (xconn->smb2.send_queue != NULL) {
3118 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3120 if (e->sendfile_header != NULL) {
3121 size_t size = 0;
3122 size_t i = 0;
3123 uint8_t *buf;
3125 for (i=0; i < e->count; i++) {
3126 size += e->vector[i].iov_len;
3129 if (size <= e->sendfile_header->length) {
3130 buf = e->sendfile_header->data;
3131 } else {
3132 buf = talloc_array(e->mem_ctx, uint8_t, size);
3133 if (buf == NULL) {
3134 return NT_STATUS_NO_MEMORY;
3138 size = 0;
3139 for (i=0; i < e->count; i++) {
3140 memcpy(buf+size,
3141 e->vector[i].iov_base,
3142 e->vector[i].iov_len);
3143 size += e->vector[i].iov_len;
3146 e->sendfile_header->data = buf;
3147 e->sendfile_header->length = size;
3148 e->count = 0;
3150 xconn->smb2.send_queue_len--;
3151 DLIST_REMOVE(xconn->smb2.send_queue, e);
3153 * This triggers the sendfile path via
3154 * the destructor.
3156 talloc_free(e->mem_ctx);
3157 continue;
3160 ret = writev(xconn->transport.sock, e->vector, e->count);
3161 if (ret == 0) {
3162 /* propagate end of file */
3163 return NT_STATUS_INTERNAL_ERROR;
3165 err = socket_error_from_errno(ret, errno, &retry);
3166 if (retry) {
3167 /* retry later */
3168 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3169 return NT_STATUS_OK;
3171 if (err != 0) {
3172 return map_nt_error_from_unix_common(err);
3174 while (ret > 0) {
3175 if (ret < e->vector[0].iov_len) {
3176 uint8_t *base;
3177 base = (uint8_t *)e->vector[0].iov_base;
3178 base += ret;
3179 e->vector[0].iov_base = (void *)base;
3180 e->vector[0].iov_len -= ret;
3181 break;
3183 ret -= e->vector[0].iov_len;
3184 e->vector += 1;
3185 e->count -= 1;
3189 * there're maybe some empty vectors at the end
3190 * which we need to skip, otherwise we would get
3191 * ret == 0 from the readv() call and return EPIPE
3193 while (e->count > 0) {
3194 if (e->vector[0].iov_len > 0) {
3195 break;
3197 e->vector += 1;
3198 e->count -= 1;
3201 if (e->count > 0) {
3202 /* we have more to write */
3203 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3204 return NT_STATUS_OK;
3207 xconn->smb2.send_queue_len--;
3208 DLIST_REMOVE(xconn->smb2.send_queue, e);
3209 talloc_free(e->mem_ctx);
3212 return NT_STATUS_OK;
3215 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3216 uint16_t fde_flags)
3218 struct smbd_server_connection *sconn = xconn->sconn;
3219 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3220 struct smbd_smb2_request *req = NULL;
3221 size_t min_recvfile_size = UINT32_MAX;
3222 int ret;
3223 int err;
3224 bool retry;
3225 NTSTATUS status;
3226 NTTIME now;
3228 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3230 * we're not supposed to do any io
3232 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3233 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3234 return NT_STATUS_OK;
3237 if (fde_flags & TEVENT_FD_WRITE) {
3238 status = smbd_smb2_flush_send_queue(xconn);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 return status;
3244 if (!(fde_flags & TEVENT_FD_READ)) {
3245 return NT_STATUS_OK;
3248 if (state->req == NULL) {
3249 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3250 return NT_STATUS_OK;
3253 again:
3254 if (!state->hdr.done) {
3255 state->hdr.done = true;
3257 state->vector.iov_base = (void *)state->hdr.nbt;
3258 state->vector.iov_len = NBT_HDR_SIZE;
3261 ret = readv(xconn->transport.sock, &state->vector, 1);
3262 if (ret == 0) {
3263 /* propagate end of file */
3264 return NT_STATUS_END_OF_FILE;
3266 err = socket_error_from_errno(ret, errno, &retry);
3267 if (retry) {
3268 /* retry later */
3269 TEVENT_FD_READABLE(xconn->transport.fde);
3270 return NT_STATUS_OK;
3272 if (err != 0) {
3273 return map_nt_error_from_unix_common(err);
3276 if (ret < state->vector.iov_len) {
3277 uint8_t *base;
3278 base = (uint8_t *)state->vector.iov_base;
3279 base += ret;
3280 state->vector.iov_base = (void *)base;
3281 state->vector.iov_len -= ret;
3282 /* we have more to read */
3283 TEVENT_FD_READABLE(xconn->transport.fde);
3284 return NT_STATUS_OK;
3287 if (state->pktlen > 0) {
3288 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3290 * Not a possible receivefile write.
3291 * Read the rest of the data.
3293 state->doing_receivefile = false;
3295 state->pktbuf = talloc_realloc(state->req,
3296 state->pktbuf,
3297 uint8_t,
3298 state->pktfull);
3299 if (state->pktbuf == NULL) {
3300 return NT_STATUS_NO_MEMORY;
3303 state->vector.iov_base = (void *)(state->pktbuf +
3304 state->pktlen);
3305 state->vector.iov_len = (state->pktfull -
3306 state->pktlen);
3308 state->pktlen = state->pktfull;
3309 goto again;
3313 * Either this is a receivefile write so we've
3314 * done a short read, or if not we have all the data.
3316 goto got_full;
3320 * Now we analyze the NBT header
3322 if (state->hdr.nbt[0] != 0x00) {
3323 state->min_recv_size = 0;
3325 state->pktfull = smb2_len(state->hdr.nbt);
3326 if (state->pktfull == 0) {
3327 goto got_full;
3330 if (state->min_recv_size != 0) {
3331 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3332 min_recvfile_size += state->min_recv_size;
3335 if (state->pktfull > min_recvfile_size) {
3337 * Might be a receivefile write. Read the SMB2 HEADER +
3338 * SMB2_WRITE header first. Set 'doing_receivefile'
3339 * as we're *attempting* receivefile write. If this
3340 * turns out not to be a SMB2_WRITE request or otherwise
3341 * not suitable then we'll just read the rest of the data
3342 * the next time this function is called.
3344 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3345 state->doing_receivefile = true;
3346 } else {
3347 state->pktlen = state->pktfull;
3350 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3351 if (state->pktbuf == NULL) {
3352 return NT_STATUS_NO_MEMORY;
3355 state->vector.iov_base = (void *)state->pktbuf;
3356 state->vector.iov_len = state->pktlen;
3358 goto again;
3360 got_full:
3362 if (state->hdr.nbt[0] != 0x00) {
3363 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3364 state->hdr.nbt[0]));
3366 req = state->req;
3367 ZERO_STRUCTP(state);
3368 state->req = req;
3369 state->min_recv_size = lp_min_receive_file_size();
3370 req = NULL;
3371 goto again;
3374 req = state->req;
3375 state->req = NULL;
3377 req->request_time = timeval_current();
3378 now = timeval_to_nttime(&req->request_time);
3380 status = smbd_smb2_inbuf_parse_compound(xconn,
3381 now,
3382 state->pktbuf,
3383 state->pktlen,
3384 req,
3385 &req->in.vector,
3386 &req->in.vector_count);
3387 if (!NT_STATUS_IS_OK(status)) {
3388 return status;
3391 if (state->doing_receivefile) {
3392 req->smb1req = talloc_zero(req, struct smb_request);
3393 if (req->smb1req == NULL) {
3394 return NT_STATUS_NO_MEMORY;
3396 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3399 ZERO_STRUCTP(state);
3401 req->current_idx = 1;
3403 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3404 req->current_idx, req->in.vector_count));
3406 status = smbd_smb2_request_validate(req);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 return status;
3411 status = smbd_smb2_request_setup_out(req);
3412 if (!NT_STATUS_IS_OK(status)) {
3413 return status;
3416 status = smbd_smb2_request_dispatch(req);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 return status;
3421 sconn->num_requests++;
3423 /* The timeout_processing function isn't run nearly
3424 often enough to implement 'max log size' without
3425 overrunning the size of the file by many megabytes.
3426 This is especially true if we are running at debug
3427 level 10. Checking every 50 SMB2s is a nice
3428 tradeoff of performance vs log file size overrun. */
3430 if ((sconn->num_requests % 50) == 0 &&
3431 need_to_check_log_size()) {
3432 change_to_root_user();
3433 check_log_size();
3436 status = smbd_smb2_request_next_incoming(sconn);
3437 if (!NT_STATUS_IS_OK(status)) {
3438 return status;
3441 return NT_STATUS_OK;
3444 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3445 struct tevent_fd *fde,
3446 uint16_t flags,
3447 void *private_data)
3449 struct smbXsrv_connection *xconn =
3450 talloc_get_type_abort(private_data,
3451 struct smbXsrv_connection);
3452 struct smbd_server_connection *sconn = xconn->sconn;
3453 NTSTATUS status;
3455 status = smbd_smb2_io_handler(xconn, flags);
3456 if (!NT_STATUS_IS_OK(status)) {
3457 smbd_server_connection_terminate(sconn, nt_errstr(status));
3458 return;