s3:smb2_server: allow smbd_smb2_send_break() with session == NULL and tcon == NULL
[Samba.git] / source3 / smbd / smb2_server.c
blob4a3ea7d4250e814a70e48961142e2f55ddd1e208
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.cipher == 0) {
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->smb2.server.cipher,
404 tf_iov, 2);
405 if (!NT_STATUS_IS_OK(status)) {
406 TALLOC_FREE(iov_alloc);
407 return status;
410 verified_buflen = taken + enc_len;
411 len = enc_len;
415 * We need the header plus the body length field
418 if (len < SMB2_HDR_BODY + 2) {
419 DEBUG(10, ("%d bytes left, expected at least %d\n",
420 (int)len, SMB2_HDR_BODY));
421 goto inval;
423 if (IVAL(hdr, 0) != SMB2_MAGIC) {
424 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
425 IVAL(hdr, 0)));
426 goto inval;
428 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
429 DEBUG(10, ("Got HDR len %d, expected %d\n",
430 SVAL(hdr, 4), SMB2_HDR_BODY));
431 goto inval;
434 full_size = len;
435 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
436 body_size = SVAL(hdr, SMB2_HDR_BODY);
438 if (next_command_ofs != 0) {
439 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
440 goto inval;
442 if (next_command_ofs > full_size) {
443 goto inval;
445 full_size = next_command_ofs;
447 if (body_size < 2) {
448 goto inval;
450 body_size &= 0xfffe;
452 if (body_size > (full_size - SMB2_HDR_BODY)) {
454 * let the caller handle the error
456 body_size = full_size - SMB2_HDR_BODY;
458 body = hdr + SMB2_HDR_BODY;
459 dyn = body + body_size;
460 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
462 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
463 struct iovec *iov_tmp = NULL;
465 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
466 struct iovec,
467 num_iov +
468 SMBD_SMB2_NUM_IOV_PER_REQ);
469 if (iov_tmp == NULL) {
470 TALLOC_FREE(iov_alloc);
471 return NT_STATUS_NO_MEMORY;
474 if (iov_alloc == NULL) {
475 memcpy(iov_tmp,
476 req->in._vector,
477 sizeof(req->in._vector));
480 iov = iov_tmp;
482 cur = &iov[num_iov];
483 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
485 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
486 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
487 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
488 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
489 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
490 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
491 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
492 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
494 taken += full_size;
497 *piov = iov;
498 *pnum_iov = num_iov;
499 return NT_STATUS_OK;
501 inval:
502 if (iov != req->in._vector) {
503 TALLOC_FREE(iov);
505 return NT_STATUS_INVALID_PARAMETER;
508 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
509 const uint8_t *_inpdu, size_t size,
510 struct smbd_smb2_request **_req)
512 struct smbd_server_connection *sconn = xconn->client->sconn;
513 struct smbd_smb2_request *req;
514 uint32_t protocol_version;
515 uint8_t *inpdu = NULL;
516 const uint8_t *inhdr = NULL;
517 uint16_t cmd;
518 uint32_t next_command_ofs;
519 NTSTATUS status;
520 NTTIME now;
522 if (size < (SMB2_HDR_BODY + 2)) {
523 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
524 return NT_STATUS_INVALID_PARAMETER;
527 inhdr = _inpdu;
529 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
530 if (protocol_version != SMB2_MAGIC) {
531 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
532 protocol_version));
533 return NT_STATUS_INVALID_PARAMETER;
536 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
537 if (cmd != SMB2_OP_NEGPROT) {
538 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
539 cmd));
540 return NT_STATUS_INVALID_PARAMETER;
543 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
544 if (next_command_ofs != 0) {
545 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
546 next_command_ofs));
547 return NT_STATUS_INVALID_PARAMETER;
550 req = smbd_smb2_request_allocate(xconn);
551 if (req == NULL) {
552 return NT_STATUS_NO_MEMORY;
554 req->sconn = sconn;
555 req->xconn = xconn;
557 inpdu = talloc_memdup(req, _inpdu, size);
558 if (inpdu == NULL) {
559 return NT_STATUS_NO_MEMORY;
562 req->request_time = timeval_current();
563 now = timeval_to_nttime(&req->request_time);
565 status = smbd_smb2_inbuf_parse_compound(xconn,
566 now,
567 inpdu,
568 size,
569 req, &req->in.vector,
570 &req->in.vector_count);
571 if (!NT_STATUS_IS_OK(status)) {
572 TALLOC_FREE(req);
573 return status;
576 req->current_idx = 1;
578 *_req = req;
579 return NT_STATUS_OK;
582 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
583 uint64_t message_id, uint64_t seq_id)
585 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
586 unsigned int offset;
587 uint64_t seq_tmp;
589 seq_tmp = xconn->smb2.credits.seq_low;
590 if (seq_id < seq_tmp) {
591 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
592 "%llu (sequence id %llu) "
593 "(granted = %u, low = %llu, range = %u)\n",
594 (unsigned long long)message_id,
595 (unsigned long long)seq_id,
596 (unsigned int)xconn->smb2.credits.granted,
597 (unsigned long long)xconn->smb2.credits.seq_low,
598 (unsigned int)xconn->smb2.credits.seq_range));
599 return false;
602 seq_tmp += xconn->smb2.credits.seq_range;
603 if (seq_id >= seq_tmp) {
604 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
605 "%llu (sequence id %llu) "
606 "(granted = %u, low = %llu, range = %u)\n",
607 (unsigned long long)message_id,
608 (unsigned long long)seq_id,
609 (unsigned int)xconn->smb2.credits.granted,
610 (unsigned long long)xconn->smb2.credits.seq_low,
611 (unsigned int)xconn->smb2.credits.seq_range));
612 return false;
615 offset = seq_id % xconn->smb2.credits.max;
617 if (bitmap_query(credits_bm, offset)) {
618 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
619 "%llu (sequence id %llu) "
620 "(granted = %u, low = %llu, range = %u) "
621 "(bm offset %u)\n",
622 (unsigned long long)message_id,
623 (unsigned long long)seq_id,
624 (unsigned int)xconn->smb2.credits.granted,
625 (unsigned long long)xconn->smb2.credits.seq_low,
626 (unsigned int)xconn->smb2.credits.seq_range,
627 offset));
628 return false;
631 /* Mark the message_ids as seen in the bitmap. */
632 bitmap_set(credits_bm, offset);
634 if (seq_id != xconn->smb2.credits.seq_low) {
635 return true;
639 * Move the window forward by all the message_id's
640 * already seen.
642 while (bitmap_query(credits_bm, offset)) {
643 DEBUG(10,("smb2_validate_sequence_number: clearing "
644 "id %llu (position %u) from bitmap\n",
645 (unsigned long long)(xconn->smb2.credits.seq_low),
646 offset));
647 bitmap_clear(credits_bm, offset);
649 xconn->smb2.credits.seq_low += 1;
650 xconn->smb2.credits.seq_range -= 1;
651 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
654 return true;
657 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
658 const uint8_t *inhdr)
660 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
661 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
662 uint16_t credit_charge = 1;
663 uint64_t i;
665 if (opcode == SMB2_OP_CANCEL) {
666 /* SMB2_CANCEL requests by definition resend messageids. */
667 return true;
670 if (xconn->smb2.credits.multicredit) {
671 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
672 credit_charge = MAX(credit_charge, 1);
675 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
676 "credits_granted %llu, "
677 "seqnum low/range: %llu/%llu\n",
678 (unsigned long long) message_id,
679 (unsigned long long) credit_charge,
680 (unsigned long long) xconn->smb2.credits.granted,
681 (unsigned long long) xconn->smb2.credits.seq_low,
682 (unsigned long long) xconn->smb2.credits.seq_range));
684 if (xconn->smb2.credits.granted < credit_charge) {
685 DEBUG(0, ("smb2_validate_message_id: client used more "
686 "credits than granted, mid %llu, charge %llu, "
687 "credits_granted %llu, "
688 "seqnum low/range: %llu/%llu\n",
689 (unsigned long long) message_id,
690 (unsigned long long) credit_charge,
691 (unsigned long long) xconn->smb2.credits.granted,
692 (unsigned long long) xconn->smb2.credits.seq_low,
693 (unsigned long long) xconn->smb2.credits.seq_range));
694 return false;
698 * now check the message ids
700 * for multi-credit requests we need to check all current mid plus
701 * the implicit mids caused by the credit charge
702 * e.g. current mid = 15, charge 5 => mark 15-19 as used
705 for (i = 0; i <= (credit_charge-1); i++) {
706 uint64_t id = message_id + i;
707 bool ok;
709 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
710 (unsigned long long)message_id,
711 credit_charge,
712 (unsigned long long)id));
714 ok = smb2_validate_sequence_number(xconn, message_id, id);
715 if (!ok) {
716 return false;
720 /* substract used credits */
721 xconn->smb2.credits.granted -= credit_charge;
723 return true;
726 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
728 int count;
729 int idx;
731 count = req->in.vector_count;
733 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
734 /* It's not a SMB2 request */
735 return NT_STATUS_INVALID_PARAMETER;
738 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
739 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
740 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
741 const uint8_t *inhdr = NULL;
743 if (hdr->iov_len != SMB2_HDR_BODY) {
744 return NT_STATUS_INVALID_PARAMETER;
747 if (body->iov_len < 2) {
748 return NT_STATUS_INVALID_PARAMETER;
751 inhdr = (const uint8_t *)hdr->iov_base;
753 /* Check the SMB2 header */
754 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
755 return NT_STATUS_INVALID_PARAMETER;
758 if (!smb2_validate_message_id(req->xconn, inhdr)) {
759 return NT_STATUS_INVALID_PARAMETER;
763 return NT_STATUS_OK;
766 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
767 const struct iovec *in_vector,
768 struct iovec *out_vector)
770 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
771 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
772 uint16_t credit_charge = 1;
773 uint16_t credits_requested;
774 uint32_t out_flags;
775 uint16_t cmd;
776 NTSTATUS out_status;
777 uint16_t credits_granted = 0;
778 uint64_t credits_possible;
779 uint16_t current_max_credits;
782 * first we grant only 1/16th of the max range.
784 * Windows also starts with the 1/16th and then grants
785 * more later. I was only able to trigger higher
786 * values, when using a very high credit charge.
788 * TODO: scale up depending on load, free memory
789 * or other stuff.
790 * Maybe also on the relationship between number
791 * of requests and the used sequence number.
792 * Which means we would grant more credits
793 * for client which use multi credit requests.
795 current_max_credits = xconn->smb2.credits.max / 16;
796 current_max_credits = MAX(current_max_credits, 1);
798 if (xconn->smb2.credits.multicredit) {
799 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
800 credit_charge = MAX(credit_charge, 1);
803 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
804 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
805 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
806 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
808 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
810 if (xconn->smb2.credits.max < credit_charge) {
811 smbd_server_connection_terminate(xconn,
812 "client error: credit charge > max credits\n");
813 return;
816 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
818 * In case we already send an async interim
819 * response, we should not grant
820 * credits on the final response.
822 credits_granted = 0;
823 } else if (credits_requested > 0) {
824 uint16_t additional_max = 0;
825 uint16_t additional_credits = credits_requested - 1;
827 switch (cmd) {
828 case SMB2_OP_NEGPROT:
829 break;
830 case SMB2_OP_SESSSETUP:
832 * Windows 2012 RC1 starts to grant
833 * additional credits
834 * with a successful session setup
836 if (NT_STATUS_IS_OK(out_status)) {
837 additional_max = 32;
839 break;
840 default:
842 * We match windows and only grant additional credits
843 * in chunks of 32.
845 additional_max = 32;
846 break;
849 additional_credits = MIN(additional_credits, additional_max);
851 credits_granted = credit_charge + additional_credits;
852 } else if (xconn->smb2.credits.granted == 0) {
854 * Make sure the client has always at least one credit
856 credits_granted = 1;
860 * sequence numbers should not wrap
862 * 1. calculate the possible credits until
863 * the sequence numbers start to wrap on 64-bit.
865 * 2. UINT64_MAX is used for Break Notifications.
867 * 2. truncate the possible credits to the maximum
868 * credits we want to grant to the client in total.
870 * 3. remove the range we'll already granted to the client
871 * this makes sure the client consumes the lowest sequence
872 * number, before we can grant additional credits.
874 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
875 if (credits_possible > 0) {
876 /* remove UINT64_MAX */
877 credits_possible -= 1;
879 credits_possible = MIN(credits_possible, current_max_credits);
880 credits_possible -= xconn->smb2.credits.seq_range;
882 credits_granted = MIN(credits_granted, credits_possible);
884 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
885 xconn->smb2.credits.granted += credits_granted;
886 xconn->smb2.credits.seq_range += credits_granted;
888 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
889 "granted %u, current possible/max %u/%u, "
890 "total granted/max/low/range %u/%u/%llu/%u\n",
891 (unsigned int)credits_requested,
892 (unsigned int)credit_charge,
893 (unsigned int)credits_granted,
894 (unsigned int)credits_possible,
895 (unsigned int)current_max_credits,
896 (unsigned int)xconn->smb2.credits.granted,
897 (unsigned int)xconn->smb2.credits.max,
898 (unsigned long long)xconn->smb2.credits.seq_low,
899 (unsigned int)xconn->smb2.credits.seq_range));
902 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
903 struct smbd_smb2_request *outreq)
905 int count, idx;
906 uint16_t total_credits = 0;
908 count = outreq->out.vector_count;
910 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
911 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
912 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
913 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
915 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
917 /* To match Windows, count up what we
918 just granted. */
919 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
920 /* Set to zero in all but the last reply. */
921 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
922 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
923 } else {
924 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
929 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
931 if (req->current_idx <= 1) {
932 if (size <= sizeof(req->out._body)) {
933 return data_blob_const(req->out._body, size);
937 return data_blob_talloc(req, NULL, size);
940 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
942 struct smbXsrv_connection *xconn = req->xconn;
943 TALLOC_CTX *mem_ctx;
944 struct iovec *vector;
945 int count;
946 int idx;
948 count = req->in.vector_count;
949 if (count <= ARRAY_SIZE(req->out._vector)) {
950 mem_ctx = req;
951 vector = req->out._vector;
952 } else {
953 vector = talloc_zero_array(req, struct iovec, count);
954 if (vector == NULL) {
955 return NT_STATUS_NO_MEMORY;
957 mem_ctx = vector;
960 vector[0].iov_base = req->out.nbt_hdr;
961 vector[0].iov_len = 4;
962 SIVAL(req->out.nbt_hdr, 0, 0);
964 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
965 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
966 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
967 uint8_t *outhdr = NULL;
968 uint8_t *outbody = NULL;
969 uint32_t next_command_ofs = 0;
970 struct iovec *current = &vector[idx];
972 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
973 /* we have a next command -
974 * setup for the error case. */
975 next_command_ofs = SMB2_HDR_BODY + 9;
978 if (idx == 1) {
979 outhdr = req->out._hdr;
980 } else {
981 outhdr = talloc_zero_array(mem_ctx, uint8_t,
982 OUTVEC_ALLOC_SIZE);
983 if (outhdr == NULL) {
984 return NT_STATUS_NO_MEMORY;
988 outbody = outhdr + SMB2_HDR_BODY;
991 * SMBD_SMB2_TF_IOV_OFS might be used later
993 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
994 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
996 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
997 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
999 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1000 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1002 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1003 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1005 /* setup the SMB2 header */
1006 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1007 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1008 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1009 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1010 SIVAL(outhdr, SMB2_HDR_STATUS,
1011 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1012 SSVAL(outhdr, SMB2_HDR_OPCODE,
1013 SVAL(inhdr, SMB2_HDR_OPCODE));
1014 SIVAL(outhdr, SMB2_HDR_FLAGS,
1015 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1016 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1017 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1018 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1019 SIVAL(outhdr, SMB2_HDR_PID,
1020 IVAL(inhdr, SMB2_HDR_PID));
1021 SIVAL(outhdr, SMB2_HDR_TID,
1022 IVAL(inhdr, SMB2_HDR_TID));
1023 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1024 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1025 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1026 inhdr + SMB2_HDR_SIGNATURE, 16);
1028 /* setup error body header */
1029 SSVAL(outbody, 0x00, 0x08 + 1);
1030 SSVAL(outbody, 0x02, 0);
1031 SIVAL(outbody, 0x04, 0);
1034 req->out.vector = vector;
1035 req->out.vector_count = count;
1037 /* setup the length of the NBT packet */
1038 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1040 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1042 return NT_STATUS_OK;
1045 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1046 const char *reason,
1047 const char *location)
1049 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1050 reason, location));
1051 exit_server_cleanly(reason);
1054 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1055 struct iovec *outvec,
1056 const struct iovec *srcvec)
1058 const uint8_t *srctf;
1059 size_t srctf_len;
1060 const uint8_t *srchdr;
1061 size_t srchdr_len;
1062 const uint8_t *srcbody;
1063 size_t srcbody_len;
1064 const uint8_t *expected_srcbody;
1065 const uint8_t *srcdyn;
1066 size_t srcdyn_len;
1067 const uint8_t *expected_srcdyn;
1068 uint8_t *dsttf;
1069 uint8_t *dsthdr;
1070 uint8_t *dstbody;
1071 uint8_t *dstdyn;
1073 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1074 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1075 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1076 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1077 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1078 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1079 expected_srcbody = srchdr + SMB2_HDR_BODY;
1080 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1081 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1082 expected_srcdyn = srcbody + 8;
1084 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1085 return false;
1088 if (srchdr_len != SMB2_HDR_BODY) {
1089 return false;
1092 if (srctf_len == SMB2_TF_HDR_SIZE) {
1093 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1094 if (dsttf == NULL) {
1095 return false;
1097 } else {
1098 dsttf = NULL;
1100 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1101 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1103 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1104 * be allocated with size OUTVEC_ALLOC_SIZE. */
1106 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1107 if (dsthdr == NULL) {
1108 return false;
1110 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1111 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1114 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1115 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1116 * then duplicate this. Else use talloc_memdup().
1119 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1120 dstbody = dsthdr + SMB2_HDR_BODY;
1121 } else {
1122 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1123 if (dstbody == NULL) {
1124 return false;
1127 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1128 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1131 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1132 * pointing to
1133 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1134 * then duplicate this. Else use talloc_memdup().
1137 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1138 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1139 } else if (srcdyn == NULL) {
1140 dstdyn = NULL;
1141 } else {
1142 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1143 if (dstdyn == NULL) {
1144 return false;
1147 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1148 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1150 return true;
1153 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1155 struct smbd_smb2_request *newreq = NULL;
1156 struct iovec *outvec = NULL;
1157 int count = req->out.vector_count;
1158 int i;
1160 newreq = smbd_smb2_request_allocate(req->xconn);
1161 if (!newreq) {
1162 return NULL;
1165 newreq->sconn = req->sconn;
1166 newreq->xconn = req->xconn;
1167 newreq->session = req->session;
1168 newreq->do_encryption = req->do_encryption;
1169 newreq->do_signing = req->do_signing;
1170 newreq->current_idx = req->current_idx;
1172 outvec = talloc_zero_array(newreq, struct iovec, count);
1173 if (!outvec) {
1174 TALLOC_FREE(newreq);
1175 return NULL;
1177 newreq->out.vector = outvec;
1178 newreq->out.vector_count = count;
1180 /* Setup the outvec's identically to req. */
1181 outvec[0].iov_base = newreq->out.nbt_hdr;
1182 outvec[0].iov_len = 4;
1183 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1185 /* Setup the vectors identically to the ones in req. */
1186 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1187 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1188 break;
1192 if (i < count) {
1193 /* Alloc failed. */
1194 TALLOC_FREE(newreq);
1195 return NULL;
1198 smb2_setup_nbt_length(newreq->out.vector,
1199 newreq->out.vector_count);
1201 return newreq;
1204 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1206 struct smbXsrv_connection *xconn = req->xconn;
1207 int first_idx = 1;
1208 struct iovec *firsttf = NULL;
1209 struct iovec *outhdr_v = NULL;
1210 uint8_t *outhdr = NULL;
1211 struct smbd_smb2_request *nreq = NULL;
1212 NTSTATUS status;
1214 /* Create a new smb2 request we'll use
1215 for the interim return. */
1216 nreq = dup_smb2_req(req);
1217 if (!nreq) {
1218 return NT_STATUS_NO_MEMORY;
1221 /* Lose the last X out vectors. They're the
1222 ones we'll be using for the async reply. */
1223 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1225 smb2_setup_nbt_length(nreq->out.vector,
1226 nreq->out.vector_count);
1228 /* Step back to the previous reply. */
1229 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1230 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1231 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1232 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1233 /* And end the chain. */
1234 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1236 /* Calculate outgoing credits */
1237 smb2_calculate_credits(req, nreq);
1239 if (DEBUGLEVEL >= 10) {
1240 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1241 (unsigned int)nreq->current_idx );
1242 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1243 (unsigned int)nreq->out.vector_count );
1244 print_req_vectors(nreq);
1248 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1249 * we need to sign/encrypt here with the last/first key we remembered
1251 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1252 status = smb2_signing_encrypt_pdu(req->first_key,
1253 xconn->smb2.server.cipher,
1254 firsttf,
1255 nreq->out.vector_count - first_idx);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1259 } else if (req->last_key.length > 0) {
1260 status = smb2_signing_sign_pdu(req->last_key,
1261 xconn->protocol,
1262 outhdr_v,
1263 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 return status;
1269 nreq->queue_entry.mem_ctx = nreq;
1270 nreq->queue_entry.vector = nreq->out.vector;
1271 nreq->queue_entry.count = nreq->out.vector_count;
1272 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1273 xconn->smb2.send_queue_len++;
1275 status = smbd_smb2_flush_send_queue(xconn);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 return status;
1280 return NT_STATUS_OK;
1283 struct smbd_smb2_request_pending_state {
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 DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1424 struct smbXsrv_connection *xconn)
1426 struct smbXsrv_channel_global0 *c = NULL;
1427 NTSTATUS status;
1428 DATA_BLOB key = data_blob_null;
1430 status = smbXsrv_session_find_channel(session, xconn, &c);
1431 if (NT_STATUS_IS_OK(status)) {
1432 key = c->signing_key;
1435 if (key.length == 0) {
1436 key = session->global->signing_key;
1439 return key;
1442 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1443 struct tevent_timer *te,
1444 struct timeval current_time,
1445 void *private_data)
1447 struct smbd_smb2_request *req =
1448 talloc_get_type_abort(private_data,
1449 struct smbd_smb2_request);
1450 struct smbXsrv_connection *xconn = req->xconn;
1451 struct smbd_smb2_request_pending_state *state = NULL;
1452 uint8_t *outhdr = NULL;
1453 const uint8_t *inhdr = NULL;
1454 uint8_t *tf = NULL;
1455 size_t tf_len = 0;
1456 uint8_t *hdr = NULL;
1457 uint8_t *body = NULL;
1458 uint8_t *dyn = NULL;
1459 uint32_t flags = 0;
1460 uint64_t session_id = 0;
1461 uint64_t message_id = 0;
1462 uint64_t nonce_high = 0;
1463 uint64_t nonce_low = 0;
1464 uint64_t async_id = 0;
1465 NTSTATUS status;
1467 TALLOC_FREE(req->async_te);
1469 /* Ensure our final reply matches the interim one. */
1470 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1471 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1472 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1473 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1474 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1476 async_id = message_id; /* keep it simple for now... */
1478 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1479 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1481 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1482 "going async\n",
1483 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1484 (unsigned long long)async_id ));
1487 * What we send is identical to a smbd_smb2_request_error
1488 * packet with an error status of STATUS_PENDING. Make use
1489 * of this fact sometime when refactoring. JRA.
1492 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1493 if (state == NULL) {
1494 smbd_server_connection_terminate(xconn,
1495 nt_errstr(NT_STATUS_NO_MEMORY));
1496 return;
1499 tf = state->buf + NBT_HDR_SIZE;
1500 tf_len = SMB2_TF_HDR_SIZE;
1502 hdr = tf + SMB2_TF_HDR_SIZE;
1503 body = hdr + SMB2_HDR_BODY;
1504 dyn = body + 8;
1506 if (req->do_encryption) {
1507 struct smbXsrv_session *x = req->session;
1509 nonce_high = x->nonce_high;
1510 nonce_low = x->nonce_low;
1512 x->nonce_low += 1;
1513 if (x->nonce_low == 0) {
1514 x->nonce_low += 1;
1515 x->nonce_high += 1;
1519 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1520 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1521 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1522 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1524 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1525 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1526 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1527 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1528 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1530 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1531 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1532 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1533 SBVAL(hdr, SMB2_HDR_PID, async_id);
1534 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1535 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1536 memcpy(hdr+SMB2_HDR_SIGNATURE,
1537 outhdr+SMB2_HDR_SIGNATURE, 16);
1539 SSVAL(body, 0x00, 0x08 + 1);
1541 SCVAL(body, 0x02, 0);
1542 SCVAL(body, 0x03, 0);
1543 SIVAL(body, 0x04, 0);
1544 /* Match W2K8R2... */
1545 SCVAL(dyn, 0x00, 0x21);
1547 state->vector[0].iov_base = (void *)state->buf;
1548 state->vector[0].iov_len = NBT_HDR_SIZE;
1550 if (req->do_encryption) {
1551 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1552 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1553 } else {
1554 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1555 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1558 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1559 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1561 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1562 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1564 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1565 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1567 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1569 /* Ensure we correctly go through crediting. Grant
1570 the credits now, and zero credits on the final
1571 response. */
1572 smb2_set_operation_credit(req->xconn,
1573 SMBD_SMB2_IN_HDR_IOV(req),
1574 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1576 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1578 if (DEBUGLVL(10)) {
1579 int i;
1581 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1582 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1583 (unsigned int)i,
1584 (unsigned int)ARRAY_SIZE(state->vector),
1585 (unsigned int)state->vector[i].iov_len);
1589 if (req->do_encryption) {
1590 struct smbXsrv_session *x = req->session;
1591 DATA_BLOB encryption_key = x->global->encryption_key;
1593 status = smb2_signing_encrypt_pdu(encryption_key,
1594 xconn->smb2.server.cipher,
1595 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1596 SMBD_SMB2_NUM_IOV_PER_REQ);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 smbd_server_connection_terminate(xconn,
1599 nt_errstr(status));
1600 return;
1602 } else if (req->do_signing) {
1603 struct smbXsrv_session *x = req->session;
1604 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1606 status = smb2_signing_sign_pdu(signing_key,
1607 xconn->protocol,
1608 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1609 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 smbd_server_connection_terminate(xconn,
1612 nt_errstr(status));
1613 return;
1617 state->queue_entry.mem_ctx = state;
1618 state->queue_entry.vector = state->vector;
1619 state->queue_entry.count = ARRAY_SIZE(state->vector);
1620 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1621 xconn->smb2.send_queue_len++;
1623 status = smbd_smb2_flush_send_queue(xconn);
1624 if (!NT_STATUS_IS_OK(status)) {
1625 smbd_server_connection_terminate(xconn,
1626 nt_errstr(status));
1627 return;
1631 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1633 struct smbXsrv_connection *xconn = req->xconn;
1634 struct smbd_smb2_request *cur;
1635 const uint8_t *inhdr;
1636 uint32_t flags;
1637 uint64_t search_message_id;
1638 uint64_t search_async_id;
1639 uint64_t found_id;
1641 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1643 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1644 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1645 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1648 * we don't need the request anymore
1649 * cancel requests never have a response
1651 DLIST_REMOVE(xconn->smb2.requests, req);
1652 TALLOC_FREE(req);
1654 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1655 const uint8_t *outhdr;
1656 uint64_t message_id;
1657 uint64_t async_id;
1659 if (cur->compound_related) {
1661 * Never cancel anything in a compound request.
1662 * Way too hard to deal with the result.
1664 continue;
1667 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1669 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1670 async_id = BVAL(outhdr, SMB2_HDR_PID);
1672 if (flags & SMB2_HDR_FLAG_ASYNC) {
1673 if (search_async_id == async_id) {
1674 found_id = async_id;
1675 break;
1677 } else {
1678 if (search_message_id == message_id) {
1679 found_id = message_id;
1680 break;
1685 if (cur && cur->subreq) {
1686 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1687 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1688 "cancel opcode[%s] mid %llu\n",
1689 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1690 (unsigned long long)found_id ));
1691 tevent_req_cancel(cur->subreq);
1694 return NT_STATUS_OK;
1697 /*************************************************************
1698 Ensure an incoming tid is a valid one for us to access.
1699 Change to the associated uid credentials and chdir to the
1700 valid tid directory.
1701 *************************************************************/
1703 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1705 const uint8_t *inhdr;
1706 uint32_t in_flags;
1707 uint32_t in_tid;
1708 struct smbXsrv_tcon *tcon;
1709 NTSTATUS status;
1710 NTTIME now = timeval_to_nttime(&req->request_time);
1712 req->tcon = NULL;
1714 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1716 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1717 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1719 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1720 in_tid = req->last_tid;
1723 req->last_tid = 0;
1725 status = smb2srv_tcon_lookup(req->session,
1726 in_tid, now, &tcon);
1727 if (!NT_STATUS_IS_OK(status)) {
1728 return status;
1731 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1732 return NT_STATUS_ACCESS_DENIED;
1735 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1736 if (!set_current_service(tcon->compat, 0, true)) {
1737 return NT_STATUS_ACCESS_DENIED;
1740 req->tcon = tcon;
1741 req->last_tid = in_tid;
1743 return NT_STATUS_OK;
1746 /*************************************************************
1747 Ensure an incoming session_id is a valid one for us to access.
1748 *************************************************************/
1750 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1752 const uint8_t *inhdr;
1753 uint32_t in_flags;
1754 uint16_t in_opcode;
1755 uint64_t in_session_id;
1756 struct smbXsrv_session *session = NULL;
1757 struct auth_session_info *session_info;
1758 NTSTATUS status;
1759 NTTIME now = timeval_to_nttime(&req->request_time);
1761 req->session = NULL;
1762 req->tcon = NULL;
1764 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1766 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1767 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1768 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1770 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1771 in_session_id = req->last_session_id;
1774 req->last_session_id = 0;
1776 /* lookup an existing session */
1777 status = smb2srv_session_lookup(req->xconn,
1778 in_session_id, now,
1779 &session);
1780 if (session) {
1781 req->session = session;
1782 req->last_session_id = in_session_id;
1784 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1785 switch (in_opcode) {
1786 case SMB2_OP_SESSSETUP:
1787 status = NT_STATUS_OK;
1788 break;
1789 default:
1790 break;
1793 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1794 switch (in_opcode) {
1795 case SMB2_OP_TCON:
1796 case SMB2_OP_CREATE:
1797 case SMB2_OP_GETINFO:
1798 case SMB2_OP_SETINFO:
1799 return NT_STATUS_INVALID_HANDLE;
1800 default:
1802 * Notice the check for
1803 * (session_info == NULL)
1804 * below.
1806 status = NT_STATUS_OK;
1807 break;
1810 if (!NT_STATUS_IS_OK(status)) {
1811 return status;
1814 session_info = session->global->auth_session_info;
1815 if (session_info == NULL) {
1816 return NT_STATUS_INVALID_HANDLE;
1819 if (in_session_id != req->xconn->client->last_session_id) {
1820 req->xconn->client->last_session_id = in_session_id;
1821 set_current_user_info(session_info->unix_info->sanitized_username,
1822 session_info->unix_info->unix_name,
1823 session_info->info->domain_name);
1826 return NT_STATUS_OK;
1829 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1830 uint32_t data_length)
1832 struct smbXsrv_connection *xconn = req->xconn;
1833 uint16_t needed_charge;
1834 uint16_t credit_charge = 1;
1835 const uint8_t *inhdr;
1837 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1839 if (xconn->smb2.credits.multicredit) {
1840 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1841 credit_charge = MAX(credit_charge, 1);
1844 needed_charge = (data_length - 1)/ 65536 + 1;
1846 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1847 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1848 credit_charge, needed_charge));
1850 if (needed_charge > credit_charge) {
1851 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1852 credit_charge, needed_charge));
1853 return NT_STATUS_INVALID_PARAMETER;
1856 return NT_STATUS_OK;
1859 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1860 size_t expected_body_size)
1862 struct iovec *inhdr_v;
1863 const uint8_t *inhdr;
1864 uint16_t opcode;
1865 const uint8_t *inbody;
1866 size_t body_size;
1867 size_t min_dyn_size = expected_body_size & 0x00000001;
1868 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1871 * The following should be checked already.
1873 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1874 return NT_STATUS_INTERNAL_ERROR;
1876 if (req->current_idx > max_idx) {
1877 return NT_STATUS_INTERNAL_ERROR;
1880 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1881 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1882 return NT_STATUS_INTERNAL_ERROR;
1884 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1885 return NT_STATUS_INTERNAL_ERROR;
1888 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1889 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1891 switch (opcode) {
1892 case SMB2_OP_IOCTL:
1893 case SMB2_OP_GETINFO:
1894 min_dyn_size = 0;
1895 break;
1896 case SMB2_OP_WRITE:
1897 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1898 if (req->smb1req->unread_bytes < min_dyn_size) {
1899 return NT_STATUS_INVALID_PARAMETER;
1902 min_dyn_size = 0;
1904 break;
1908 * Now check the expected body size,
1909 * where the last byte might be in the
1910 * dynamic section..
1912 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1913 return NT_STATUS_INVALID_PARAMETER;
1915 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1916 return NT_STATUS_INVALID_PARAMETER;
1919 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1921 body_size = SVAL(inbody, 0x00);
1922 if (body_size != expected_body_size) {
1923 return NT_STATUS_INVALID_PARAMETER;
1926 return NT_STATUS_OK;
1929 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1931 struct smbXsrv_connection *xconn = req->xconn;
1932 const struct smbd_smb2_dispatch_table *call = NULL;
1933 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1934 const uint8_t *inhdr;
1935 uint16_t opcode;
1936 uint32_t flags;
1937 uint64_t mid;
1938 NTSTATUS status;
1939 NTSTATUS session_status;
1940 uint32_t allowed_flags;
1941 NTSTATUS return_value;
1942 struct smbXsrv_session *x = NULL;
1943 bool signing_required = false;
1944 bool encryption_required = false;
1946 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1948 DO_PROFILE_INC(request);
1950 /* TODO: verify more things */
1952 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1953 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1954 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1955 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1956 smb2_opcode_name(opcode),
1957 (unsigned long long)mid));
1959 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1961 * once the protocol is negotiated
1962 * SMB2_OP_NEGPROT is not allowed anymore
1964 if (opcode == SMB2_OP_NEGPROT) {
1965 /* drop the connection */
1966 return NT_STATUS_INVALID_PARAMETER;
1968 } else {
1970 * if the protocol is not negotiated yet
1971 * only SMB2_OP_NEGPROT is allowed.
1973 if (opcode != SMB2_OP_NEGPROT) {
1974 /* drop the connection */
1975 return NT_STATUS_INVALID_PARAMETER;
1980 * Check if the client provided a valid session id,
1981 * if so smbd_smb2_request_check_session() calls
1982 * set_current_user_info().
1984 * As some command don't require a valid session id
1985 * we defer the check of the session_status
1987 session_status = smbd_smb2_request_check_session(req);
1988 x = req->session;
1989 if (x != NULL) {
1990 signing_required = x->global->signing_required;
1991 encryption_required = x->global->encryption_required;
1993 if (opcode == SMB2_OP_SESSSETUP &&
1994 x->global->signing_key.length > 0) {
1995 signing_required = true;
1999 req->do_signing = false;
2000 req->do_encryption = false;
2001 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2002 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2003 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2005 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2006 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2007 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2008 (unsigned long long)x->global->session_wire_id,
2009 (unsigned long long)tf_session_id));
2011 * TODO: windows allows this...
2012 * should we drop the connection?
2014 * For now we just return ACCESS_DENIED
2015 * (Windows clients never trigger this)
2016 * and wait for an update of [MS-SMB2].
2018 return smbd_smb2_request_error(req,
2019 NT_STATUS_ACCESS_DENIED);
2022 req->do_encryption = true;
2025 if (encryption_required && !req->do_encryption) {
2026 return smbd_smb2_request_error(req,
2027 NT_STATUS_ACCESS_DENIED);
2030 call = smbd_smb2_call(opcode);
2031 if (call == NULL) {
2032 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2035 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2036 SMB2_HDR_FLAG_SIGNED |
2037 SMB2_HDR_FLAG_DFS;
2038 if (opcode == SMB2_OP_CANCEL) {
2039 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2041 if ((flags & ~allowed_flags) != 0) {
2042 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2045 if (flags & SMB2_HDR_FLAG_CHAINED) {
2047 * This check is mostly for giving the correct error code
2048 * for compounded requests.
2050 if (!NT_STATUS_IS_OK(session_status)) {
2051 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2053 } else {
2054 req->compat_chain_fsp = NULL;
2057 if (req->do_encryption) {
2058 signing_required = false;
2059 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2060 DATA_BLOB signing_key = data_blob_null;
2062 if (x == NULL) {
2064 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2065 * If the SMB2 header of the SMB2 NEGOTIATE
2066 * request has the SMB2_FLAGS_SIGNED bit set in the
2067 * Flags field, the server MUST fail the request
2068 * with STATUS_INVALID_PARAMETER.
2070 * Microsoft test tool checks this.
2073 if ((opcode == SMB2_OP_NEGPROT) &&
2074 (flags & SMB2_HDR_FLAG_SIGNED)) {
2075 status = NT_STATUS_INVALID_PARAMETER;
2076 } else {
2077 status = NT_STATUS_USER_SESSION_DELETED;
2079 return smbd_smb2_request_error(req, status);
2082 signing_key = smbd_smb2_signing_key(x, xconn);
2085 * If we have a signing key, we should
2086 * sign the response
2088 if (signing_key.length > 0) {
2089 req->do_signing = true;
2092 status = smb2_signing_check_pdu(signing_key,
2093 xconn->protocol,
2094 SMBD_SMB2_IN_HDR_IOV(req),
2095 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 return smbd_smb2_request_error(req, status);
2101 * Now that we know the request was correctly signed
2102 * we have to sign the response too.
2104 req->do_signing = true;
2106 if (!NT_STATUS_IS_OK(session_status)) {
2107 return smbd_smb2_request_error(req, session_status);
2109 } else if (opcode == SMB2_OP_CANCEL) {
2110 /* Cancel requests are allowed to skip the signing */
2111 } else if (signing_required) {
2113 * If signing is required we try to sign
2114 * a possible error response
2116 req->do_signing = true;
2117 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2120 if (flags & SMB2_HDR_FLAG_CHAINED) {
2121 req->compound_related = true;
2124 if (call->need_session) {
2125 if (!NT_STATUS_IS_OK(session_status)) {
2126 return smbd_smb2_request_error(req, session_status);
2130 if (call->need_tcon) {
2131 SMB_ASSERT(call->need_session);
2134 * This call needs to be run as user.
2136 * smbd_smb2_request_check_tcon()
2137 * calls change_to_user() on success.
2139 status = smbd_smb2_request_check_tcon(req);
2140 if (!NT_STATUS_IS_OK(status)) {
2141 return smbd_smb2_request_error(req, status);
2143 if (req->tcon->global->encryption_required) {
2144 encryption_required = true;
2146 if (encryption_required && !req->do_encryption) {
2147 return smbd_smb2_request_error(req,
2148 NT_STATUS_ACCESS_DENIED);
2152 if (call->fileid_ofs != 0) {
2153 size_t needed = call->fileid_ofs + 16;
2154 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2155 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2156 uint64_t file_id_persistent;
2157 uint64_t file_id_volatile;
2158 struct files_struct *fsp;
2160 SMB_ASSERT(call->need_tcon);
2162 if (needed > body_size) {
2163 return smbd_smb2_request_error(req,
2164 NT_STATUS_INVALID_PARAMETER);
2167 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2168 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2170 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2171 if (fsp == NULL) {
2172 if (!call->allow_invalid_fileid) {
2173 return smbd_smb2_request_error(req,
2174 NT_STATUS_FILE_CLOSED);
2177 if (file_id_persistent != UINT64_MAX) {
2178 return smbd_smb2_request_error(req,
2179 NT_STATUS_FILE_CLOSED);
2181 if (file_id_volatile != UINT64_MAX) {
2182 return smbd_smb2_request_error(req,
2183 NT_STATUS_FILE_CLOSED);
2188 if (call->as_root) {
2189 SMB_ASSERT(call->fileid_ofs == 0);
2190 /* This call needs to be run as root */
2191 change_to_root_user();
2192 } else {
2193 SMB_ASSERT(call->need_tcon);
2196 #define _INBYTES(_r) \
2197 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2199 switch (opcode) {
2200 case SMB2_OP_NEGPROT:
2201 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2202 req->profile, _INBYTES(req));
2203 return_value = smbd_smb2_request_process_negprot(req);
2204 break;
2206 case SMB2_OP_SESSSETUP:
2207 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2208 req->profile, _INBYTES(req));
2209 return_value = smbd_smb2_request_process_sesssetup(req);
2210 break;
2212 case SMB2_OP_LOGOFF:
2213 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2214 req->profile, _INBYTES(req));
2215 return_value = smbd_smb2_request_process_logoff(req);
2216 break;
2218 case SMB2_OP_TCON:
2219 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2220 req->profile, _INBYTES(req));
2221 return_value = smbd_smb2_request_process_tcon(req);
2222 break;
2224 case SMB2_OP_TDIS:
2225 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2226 req->profile, _INBYTES(req));
2227 return_value = smbd_smb2_request_process_tdis(req);
2228 break;
2230 case SMB2_OP_CREATE:
2231 if (req->subreq == NULL) {
2232 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2233 req->profile, _INBYTES(req));
2234 } else {
2235 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2237 return_value = smbd_smb2_request_process_create(req);
2238 break;
2240 case SMB2_OP_CLOSE:
2241 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2242 req->profile, _INBYTES(req));
2243 return_value = smbd_smb2_request_process_close(req);
2244 break;
2246 case SMB2_OP_FLUSH:
2247 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2248 req->profile, _INBYTES(req));
2249 return_value = smbd_smb2_request_process_flush(req);
2250 break;
2252 case SMB2_OP_READ:
2253 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2254 req->profile, _INBYTES(req));
2255 return_value = smbd_smb2_request_process_read(req);
2256 break;
2258 case SMB2_OP_WRITE:
2259 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2260 req->profile, _INBYTES(req));
2261 return_value = smbd_smb2_request_process_write(req);
2262 break;
2264 case SMB2_OP_LOCK:
2265 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2266 req->profile, _INBYTES(req));
2267 return_value = smbd_smb2_request_process_lock(req);
2268 break;
2270 case SMB2_OP_IOCTL:
2271 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2272 req->profile, _INBYTES(req));
2273 return_value = smbd_smb2_request_process_ioctl(req);
2274 break;
2276 case SMB2_OP_CANCEL:
2277 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2278 req->profile, _INBYTES(req));
2279 return_value = smbd_smb2_request_process_cancel(req);
2280 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2281 break;
2283 case SMB2_OP_KEEPALIVE:
2284 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2285 req->profile, _INBYTES(req));
2286 return_value = smbd_smb2_request_process_keepalive(req);
2287 break;
2289 case SMB2_OP_FIND:
2290 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2291 req->profile, _INBYTES(req));
2292 return_value = smbd_smb2_request_process_find(req);
2293 break;
2295 case SMB2_OP_NOTIFY:
2296 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2297 req->profile, _INBYTES(req));
2298 return_value = smbd_smb2_request_process_notify(req);
2299 break;
2301 case SMB2_OP_GETINFO:
2302 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2303 req->profile, _INBYTES(req));
2304 return_value = smbd_smb2_request_process_getinfo(req);
2305 break;
2307 case SMB2_OP_SETINFO:
2308 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2309 req->profile, _INBYTES(req));
2310 return_value = smbd_smb2_request_process_setinfo(req);
2311 break;
2313 case SMB2_OP_BREAK:
2314 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2315 req->profile, _INBYTES(req));
2316 return_value = smbd_smb2_request_process_break(req);
2317 break;
2319 default:
2320 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2321 break;
2323 return return_value;
2326 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2328 struct smbXsrv_connection *xconn = req->xconn;
2329 int first_idx = 1;
2330 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2331 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2332 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2333 NTSTATUS status;
2335 req->subreq = NULL;
2336 TALLOC_FREE(req->async_te);
2338 if (req->do_encryption &&
2339 (firsttf->iov_len == 0) &&
2340 (req->first_key.length == 0) &&
2341 (req->session != NULL) &&
2342 (req->session->global->encryption_key.length != 0))
2344 DATA_BLOB encryption_key = req->session->global->encryption_key;
2345 uint8_t *tf;
2346 uint64_t session_id = req->session->global->session_wire_id;
2347 struct smbXsrv_session *x = req->session;
2348 uint64_t nonce_high;
2349 uint64_t nonce_low;
2351 nonce_high = x->nonce_high;
2352 nonce_low = x->nonce_low;
2354 x->nonce_low += 1;
2355 if (x->nonce_low == 0) {
2356 x->nonce_low += 1;
2357 x->nonce_high += 1;
2361 * We need to place the SMB2_TRANSFORM header before the
2362 * first SMB2 header
2366 * we need to remember the encryption key
2367 * and defer the signing/encryption until
2368 * we are sure that we do not change
2369 * the header again.
2371 req->first_key = data_blob_dup_talloc(req, encryption_key);
2372 if (req->first_key.data == NULL) {
2373 return NT_STATUS_NO_MEMORY;
2376 tf = talloc_zero_array(req, uint8_t,
2377 SMB2_TF_HDR_SIZE);
2378 if (tf == NULL) {
2379 return NT_STATUS_NO_MEMORY;
2382 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2383 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2384 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2385 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2387 firsttf->iov_base = (void *)tf;
2388 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2391 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2392 (req->last_key.length > 0) &&
2393 (firsttf->iov_len == 0))
2395 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2396 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2399 * As we are sure the header of the last request in the
2400 * compound chain will not change, we can to sign here
2401 * with the last signing key we remembered.
2403 status = smb2_signing_sign_pdu(req->last_key,
2404 xconn->protocol,
2405 lasthdr,
2406 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 return status;
2411 if (req->last_key.length > 0) {
2412 data_blob_clear_free(&req->last_key);
2415 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2416 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2418 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2420 if (req->current_idx < req->out.vector_count) {
2422 * We must process the remaining compound
2423 * SMB2 requests before any new incoming SMB2
2424 * requests. This is because incoming SMB2
2425 * requests may include a cancel for a
2426 * compound request we haven't processed
2427 * yet.
2429 struct tevent_immediate *im = tevent_create_immediate(req);
2430 if (!im) {
2431 return NT_STATUS_NO_MEMORY;
2434 if (req->do_signing && firsttf->iov_len == 0) {
2435 struct smbXsrv_session *x = req->session;
2436 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2439 * we need to remember the signing key
2440 * and defer the signing until
2441 * we are sure that we do not change
2442 * the header again.
2444 req->last_key = data_blob_dup_talloc(req, signing_key);
2445 if (req->last_key.data == NULL) {
2446 return NT_STATUS_NO_MEMORY;
2450 tevent_schedule_immediate(im,
2451 req->sconn->ev_ctx,
2452 smbd_smb2_request_dispatch_immediate,
2453 req);
2454 return NT_STATUS_OK;
2457 if (req->compound_related) {
2458 req->compound_related = false;
2461 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2463 /* Set credit for these operations (zero credits if this
2464 is a final reply for an async operation). */
2465 smb2_calculate_credits(req, req);
2468 * now check if we need to sign the current response
2470 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2471 status = smb2_signing_encrypt_pdu(req->first_key,
2472 xconn->smb2.server.cipher,
2473 firsttf,
2474 req->out.vector_count - first_idx);
2475 if (!NT_STATUS_IS_OK(status)) {
2476 return status;
2478 } else if (req->do_signing) {
2479 struct smbXsrv_session *x = req->session;
2480 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2482 status = smb2_signing_sign_pdu(signing_key,
2483 xconn->protocol,
2484 outhdr,
2485 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 return status;
2490 if (req->first_key.length > 0) {
2491 data_blob_clear_free(&req->first_key);
2494 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2495 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2496 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2497 /* Dynamic part is NULL. Chop it off,
2498 We're going to send it via sendfile. */
2499 req->out.vector_count -= 1;
2503 * We're done with this request -
2504 * move it off the "being processed" queue.
2506 DLIST_REMOVE(xconn->smb2.requests, req);
2508 req->queue_entry.mem_ctx = req;
2509 req->queue_entry.vector = req->out.vector;
2510 req->queue_entry.count = req->out.vector_count;
2511 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2512 xconn->smb2.send_queue_len++;
2514 status = smbd_smb2_flush_send_queue(xconn);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 return status;
2519 return NT_STATUS_OK;
2522 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2524 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2525 struct tevent_immediate *im,
2526 void *private_data)
2528 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2529 struct smbd_smb2_request);
2530 struct smbXsrv_connection *xconn = req->xconn;
2531 NTSTATUS status;
2533 TALLOC_FREE(im);
2535 if (DEBUGLEVEL >= 10) {
2536 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2537 req->current_idx, req->in.vector_count));
2538 print_req_vectors(req);
2541 status = smbd_smb2_request_dispatch(req);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 smbd_server_connection_terminate(xconn, nt_errstr(status));
2544 return;
2547 status = smbd_smb2_request_next_incoming(xconn);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 smbd_server_connection_terminate(xconn, nt_errstr(status));
2550 return;
2554 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2555 NTSTATUS status,
2556 DATA_BLOB body, DATA_BLOB *dyn,
2557 const char *location)
2559 uint8_t *outhdr;
2560 struct iovec *outbody_v;
2561 struct iovec *outdyn_v;
2562 uint32_t next_command_ofs;
2564 DEBUG(10,("smbd_smb2_request_done_ex: "
2565 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2566 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2567 dyn ? "yes": "no",
2568 (unsigned int)(dyn ? dyn->length : 0),
2569 location));
2571 if (body.length < 2) {
2572 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2575 if ((body.length % 2) != 0) {
2576 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2579 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2580 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2581 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2583 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2584 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2586 outbody_v->iov_base = (void *)body.data;
2587 outbody_v->iov_len = body.length;
2589 if (dyn) {
2590 outdyn_v->iov_base = (void *)dyn->data;
2591 outdyn_v->iov_len = dyn->length;
2592 } else {
2593 outdyn_v->iov_base = NULL;
2594 outdyn_v->iov_len = 0;
2597 /* see if we need to recalculate the offset to the next response */
2598 if (next_command_ofs > 0) {
2599 next_command_ofs = SMB2_HDR_BODY;
2600 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2601 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2604 if ((next_command_ofs % 8) != 0) {
2605 size_t pad_size = 8 - (next_command_ofs % 8);
2606 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2608 * if the dyn buffer is empty
2609 * we can use it to add padding
2611 uint8_t *pad;
2613 pad = talloc_zero_array(req,
2614 uint8_t, pad_size);
2615 if (pad == NULL) {
2616 return smbd_smb2_request_error(req,
2617 NT_STATUS_NO_MEMORY);
2620 outdyn_v->iov_base = (void *)pad;
2621 outdyn_v->iov_len = pad_size;
2622 } else {
2624 * For now we copy the dynamic buffer
2625 * and add the padding to the new buffer
2627 size_t old_size;
2628 uint8_t *old_dyn;
2629 size_t new_size;
2630 uint8_t *new_dyn;
2632 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2633 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2635 new_size = old_size + pad_size;
2636 new_dyn = talloc_zero_array(req,
2637 uint8_t, new_size);
2638 if (new_dyn == NULL) {
2639 return smbd_smb2_request_error(req,
2640 NT_STATUS_NO_MEMORY);
2643 memcpy(new_dyn, old_dyn, old_size);
2644 memset(new_dyn + old_size, 0, pad_size);
2646 outdyn_v->iov_base = (void *)new_dyn;
2647 outdyn_v->iov_len = new_size;
2649 next_command_ofs += pad_size;
2652 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2654 return smbd_smb2_request_reply(req);
2657 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2658 NTSTATUS status,
2659 DATA_BLOB *info,
2660 const char *location)
2662 struct smbXsrv_connection *xconn = req->xconn;
2663 DATA_BLOB body;
2664 DATA_BLOB _dyn;
2665 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2666 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2668 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2669 req->current_idx, nt_errstr(status), info ? " +info" : "",
2670 location));
2672 if (unread_bytes) {
2673 /* Recvfile error. Drain incoming socket. */
2674 size_t ret;
2676 errno = 0;
2677 ret = drain_socket(xconn->transport.sock, unread_bytes);
2678 if (ret != unread_bytes) {
2679 NTSTATUS error;
2681 if (errno == 0) {
2682 error = NT_STATUS_IO_DEVICE_ERROR;
2683 } else {
2684 error = map_nt_error_from_unix_common(errno);
2687 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2688 "ret[%u] errno[%d] => %s\n",
2689 (unsigned)unread_bytes,
2690 (unsigned)ret, errno, nt_errstr(error)));
2691 return error;
2695 body.data = outhdr + SMB2_HDR_BODY;
2696 body.length = 8;
2697 SSVAL(body.data, 0, 9);
2699 if (info) {
2700 SIVAL(body.data, 0x04, info->length);
2701 } else {
2702 /* Allocated size of req->out.vector[i].iov_base
2703 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2704 * 1 byte without having to do an alloc.
2706 info = &_dyn;
2707 info->data = ((uint8_t *)outhdr) +
2708 OUTVEC_ALLOC_SIZE - 1;
2709 info->length = 1;
2710 SCVAL(info->data, 0, 0);
2714 * Note: Even if there is an error, continue to process the request.
2715 * per MS-SMB2.
2718 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2722 struct smbd_smb2_send_break_state {
2723 struct smbd_smb2_send_queue queue_entry;
2724 uint8_t nbt_hdr[NBT_HDR_SIZE];
2725 uint8_t tf[SMB2_TF_HDR_SIZE];
2726 uint8_t hdr[SMB2_HDR_BODY];
2727 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2728 uint8_t body[1];
2731 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2732 struct smbXsrv_session *session,
2733 struct smbXsrv_tcon *tcon,
2734 const uint8_t *body,
2735 size_t body_len)
2737 struct smbd_smb2_send_break_state *state;
2738 bool do_encryption = false;
2739 uint64_t session_wire_id = 0;
2740 uint64_t nonce_high = 0;
2741 uint64_t nonce_low = 0;
2742 NTSTATUS status;
2743 size_t statelen;
2745 if (session != NULL) {
2746 session_wire_id = session->global->session_wire_id;
2747 do_encryption = session->global->encryption_required;
2748 if (tcon->global->encryption_required) {
2749 do_encryption = true;
2753 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2754 body_len;
2756 state = talloc_zero_size(xconn, statelen);
2757 if (state == NULL) {
2758 return NT_STATUS_NO_MEMORY;
2760 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2762 if (do_encryption) {
2763 nonce_high = session->nonce_high;
2764 nonce_low = session->nonce_low;
2766 session->nonce_low += 1;
2767 if (session->nonce_low == 0) {
2768 session->nonce_low += 1;
2769 session->nonce_high += 1;
2773 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2774 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2775 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2776 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2778 SIVAL(state->hdr, 0, SMB2_MAGIC);
2779 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2780 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2781 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2782 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2783 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2784 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2785 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2786 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2787 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2788 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2789 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2790 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2792 state->vector[0] = (struct iovec) {
2793 .iov_base = state->nbt_hdr,
2794 .iov_len = sizeof(state->nbt_hdr)
2797 if (do_encryption) {
2798 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2799 .iov_base = state->tf,
2800 .iov_len = sizeof(state->tf)
2802 } else {
2803 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2804 .iov_base = NULL,
2805 .iov_len = 0
2809 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2810 .iov_base = state->hdr,
2811 .iov_len = sizeof(state->hdr)
2814 memcpy(state->body, body, body_len);
2816 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2817 .iov_base = state->body,
2818 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2822 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2825 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2827 if (do_encryption) {
2828 DATA_BLOB encryption_key = session->global->encryption_key;
2830 status = smb2_signing_encrypt_pdu(encryption_key,
2831 xconn->smb2.server.cipher,
2832 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2833 SMBD_SMB2_NUM_IOV_PER_REQ);
2834 if (!NT_STATUS_IS_OK(status)) {
2835 return status;
2839 state->queue_entry.mem_ctx = state;
2840 state->queue_entry.vector = state->vector;
2841 state->queue_entry.count = ARRAY_SIZE(state->vector);
2842 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2843 xconn->smb2.send_queue_len++;
2845 status = smbd_smb2_flush_send_queue(xconn);
2846 if (!NT_STATUS_IS_OK(status)) {
2847 return status;
2850 return NT_STATUS_OK;
2853 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2854 struct smbXsrv_session *session,
2855 struct smbXsrv_tcon *tcon,
2856 struct smbXsrv_open *op,
2857 uint8_t oplock_level)
2859 uint8_t body[0x18];
2861 SSVAL(body, 0x00, sizeof(body));
2862 SCVAL(body, 0x02, oplock_level);
2863 SCVAL(body, 0x03, 0); /* reserved */
2864 SIVAL(body, 0x04, 0); /* reserved */
2865 SBVAL(body, 0x08, op->global->open_persistent_id);
2866 SBVAL(body, 0x10, op->global->open_volatile_id);
2868 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2871 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2873 NTSTATUS status;
2874 uint32_t flags;
2875 uint64_t file_id_persistent;
2876 uint64_t file_id_volatile;
2877 struct smbXsrv_open *op = NULL;
2878 struct files_struct *fsp = NULL;
2879 const uint8_t *body = NULL;
2882 * This is only called with a pktbuf
2883 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2884 * bytes
2887 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2888 /* Transform header. Cannot recvfile. */
2889 return false;
2891 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2892 /* Not SMB2. Normal error path will cope. */
2893 return false;
2895 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2896 /* Not SMB2. Normal error path will cope. */
2897 return false;
2899 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2900 /* Needs to be a WRITE. */
2901 return false;
2903 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2904 /* Chained. Cannot recvfile. */
2905 return false;
2907 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2908 if (flags & SMB2_HDR_FLAG_CHAINED) {
2909 /* Chained. Cannot recvfile. */
2910 return false;
2912 if (flags & SMB2_HDR_FLAG_SIGNED) {
2913 /* Signed. Cannot recvfile. */
2914 return false;
2917 body = &state->pktbuf[SMB2_HDR_BODY];
2919 file_id_persistent = BVAL(body, 0x10);
2920 file_id_volatile = BVAL(body, 0x18);
2922 status = smb2srv_open_lookup(state->req->xconn,
2923 file_id_persistent,
2924 file_id_volatile,
2925 0, /* now */
2926 &op);
2927 if (!NT_STATUS_IS_OK(status)) {
2928 return false;
2931 fsp = op->compat;
2932 if (fsp == NULL) {
2933 return false;
2935 if (fsp->conn == NULL) {
2936 return false;
2939 if (IS_IPC(fsp->conn)) {
2940 return false;
2942 if (IS_PRINT(fsp->conn)) {
2943 return false;
2946 DEBUG(10,("Doing recvfile write len = %u\n",
2947 (unsigned int)(state->pktfull - state->pktlen)));
2949 return true;
2952 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2954 struct smbd_server_connection *sconn = xconn->client->sconn;
2955 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2956 size_t max_send_queue_len;
2957 size_t cur_send_queue_len;
2959 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2961 * we're not supposed to do any io
2963 return NT_STATUS_OK;
2966 if (state->req != NULL) {
2968 * if there is already a tstream_readv_pdu
2969 * pending, we are done.
2971 return NT_STATUS_OK;
2974 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2975 cur_send_queue_len = xconn->smb2.send_queue_len;
2977 if (cur_send_queue_len > max_send_queue_len) {
2979 * if we have a lot of requests to send,
2980 * we wait until they are on the wire until we
2981 * ask for the next request.
2983 return NT_STATUS_OK;
2986 /* ask for the next request */
2987 ZERO_STRUCTP(state);
2988 state->req = smbd_smb2_request_allocate(xconn);
2989 if (state->req == NULL) {
2990 return NT_STATUS_NO_MEMORY;
2992 state->req->sconn = sconn;
2993 state->req->xconn = xconn;
2994 state->min_recv_size = lp_min_receive_file_size();
2996 TEVENT_FD_READABLE(xconn->transport.fde);
2998 return NT_STATUS_OK;
3001 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3002 const uint8_t *inpdu, size_t size)
3004 struct smbd_server_connection *sconn = xconn->client->sconn;
3005 NTSTATUS status;
3006 struct smbd_smb2_request *req = NULL;
3008 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3009 (unsigned int)size));
3011 status = smbd_initialize_smb2(xconn);
3012 if (!NT_STATUS_IS_OK(status)) {
3013 smbd_server_connection_terminate(xconn, nt_errstr(status));
3014 return;
3017 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3018 if (!NT_STATUS_IS_OK(status)) {
3019 smbd_server_connection_terminate(xconn, nt_errstr(status));
3020 return;
3023 status = smbd_smb2_request_validate(req);
3024 if (!NT_STATUS_IS_OK(status)) {
3025 smbd_server_connection_terminate(xconn, nt_errstr(status));
3026 return;
3029 status = smbd_smb2_request_setup_out(req);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 smbd_server_connection_terminate(xconn, nt_errstr(status));
3032 return;
3035 #ifdef WITH_PROFILE
3037 * this was already counted at the SMB1 layer =>
3038 * smbd_smb2_request_dispatch() should not count it twice.
3040 if (profile_p->request_stats.count > 0) {
3041 profile_p->request_stats.count--;
3043 #endif
3044 status = smbd_smb2_request_dispatch(req);
3045 if (!NT_STATUS_IS_OK(status)) {
3046 smbd_server_connection_terminate(xconn, nt_errstr(status));
3047 return;
3050 status = smbd_smb2_request_next_incoming(xconn);
3051 if (!NT_STATUS_IS_OK(status)) {
3052 smbd_server_connection_terminate(xconn, nt_errstr(status));
3053 return;
3056 sconn->num_requests++;
3059 static int socket_error_from_errno(int ret,
3060 int sys_errno,
3061 bool *retry)
3063 *retry = false;
3065 if (ret >= 0) {
3066 return 0;
3069 if (ret != -1) {
3070 return EIO;
3073 if (sys_errno == 0) {
3074 return EIO;
3077 if (sys_errno == EINTR) {
3078 *retry = true;
3079 return sys_errno;
3082 if (sys_errno == EINPROGRESS) {
3083 *retry = true;
3084 return sys_errno;
3087 if (sys_errno == EAGAIN) {
3088 *retry = true;
3089 return sys_errno;
3092 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3093 if (sys_errno == ENOMEM) {
3094 *retry = true;
3095 return sys_errno;
3098 #ifdef EWOULDBLOCK
3099 #if EWOULDBLOCK != EAGAIN
3100 if (sys_errno == EWOULDBLOCK) {
3101 *retry = true;
3102 return sys_errno;
3104 #endif
3105 #endif
3107 return sys_errno;
3110 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3112 int ret;
3113 int err;
3114 bool retry;
3116 if (xconn->smb2.send_queue == NULL) {
3117 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3118 return NT_STATUS_OK;
3121 while (xconn->smb2.send_queue != NULL) {
3122 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3124 if (e->sendfile_header != NULL) {
3125 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3126 size_t size = 0;
3127 size_t i = 0;
3128 uint8_t *buf;
3130 for (i=0; i < e->count; i++) {
3131 size += e->vector[i].iov_len;
3134 if (size <= e->sendfile_header->length) {
3135 buf = e->sendfile_header->data;
3136 } else {
3137 buf = talloc_array(e->mem_ctx, uint8_t, size);
3138 if (buf == NULL) {
3139 return NT_STATUS_NO_MEMORY;
3143 size = 0;
3144 for (i=0; i < e->count; i++) {
3145 memcpy(buf+size,
3146 e->vector[i].iov_base,
3147 e->vector[i].iov_len);
3148 size += e->vector[i].iov_len;
3151 e->sendfile_header->data = buf;
3152 e->sendfile_header->length = size;
3153 e->sendfile_status = &status;
3154 e->count = 0;
3156 xconn->smb2.send_queue_len--;
3157 DLIST_REMOVE(xconn->smb2.send_queue, e);
3159 * This triggers the sendfile path via
3160 * the destructor.
3162 talloc_free(e->mem_ctx);
3164 if (!NT_STATUS_IS_OK(status)) {
3165 return status;
3167 continue;
3170 ret = writev(xconn->transport.sock, e->vector, e->count);
3171 if (ret == 0) {
3172 /* propagate end of file */
3173 return NT_STATUS_INTERNAL_ERROR;
3175 err = socket_error_from_errno(ret, errno, &retry);
3176 if (retry) {
3177 /* retry later */
3178 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3179 return NT_STATUS_OK;
3181 if (err != 0) {
3182 return map_nt_error_from_unix_common(err);
3184 while (ret > 0) {
3185 if (ret < e->vector[0].iov_len) {
3186 uint8_t *base;
3187 base = (uint8_t *)e->vector[0].iov_base;
3188 base += ret;
3189 e->vector[0].iov_base = (void *)base;
3190 e->vector[0].iov_len -= ret;
3191 break;
3193 ret -= e->vector[0].iov_len;
3194 e->vector += 1;
3195 e->count -= 1;
3199 * there're maybe some empty vectors at the end
3200 * which we need to skip, otherwise we would get
3201 * ret == 0 from the readv() call and return EPIPE
3203 while (e->count > 0) {
3204 if (e->vector[0].iov_len > 0) {
3205 break;
3207 e->vector += 1;
3208 e->count -= 1;
3211 if (e->count > 0) {
3212 /* we have more to write */
3213 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3214 return NT_STATUS_OK;
3217 xconn->smb2.send_queue_len--;
3218 DLIST_REMOVE(xconn->smb2.send_queue, e);
3219 talloc_free(e->mem_ctx);
3222 return NT_STATUS_OK;
3225 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3226 uint16_t fde_flags)
3228 struct smbd_server_connection *sconn = xconn->client->sconn;
3229 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3230 struct smbd_smb2_request *req = NULL;
3231 size_t min_recvfile_size = UINT32_MAX;
3232 int ret;
3233 int err;
3234 bool retry;
3235 NTSTATUS status;
3236 NTTIME now;
3238 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3240 * we're not supposed to do any io
3242 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3243 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3244 return NT_STATUS_OK;
3247 if (fde_flags & TEVENT_FD_WRITE) {
3248 status = smbd_smb2_flush_send_queue(xconn);
3249 if (!NT_STATUS_IS_OK(status)) {
3250 return status;
3254 if (!(fde_flags & TEVENT_FD_READ)) {
3255 return NT_STATUS_OK;
3258 if (state->req == NULL) {
3259 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3260 return NT_STATUS_OK;
3263 again:
3264 if (!state->hdr.done) {
3265 state->hdr.done = true;
3267 state->vector.iov_base = (void *)state->hdr.nbt;
3268 state->vector.iov_len = NBT_HDR_SIZE;
3271 ret = readv(xconn->transport.sock, &state->vector, 1);
3272 if (ret == 0) {
3273 /* propagate end of file */
3274 return NT_STATUS_END_OF_FILE;
3276 err = socket_error_from_errno(ret, errno, &retry);
3277 if (retry) {
3278 /* retry later */
3279 TEVENT_FD_READABLE(xconn->transport.fde);
3280 return NT_STATUS_OK;
3282 if (err != 0) {
3283 return map_nt_error_from_unix_common(err);
3286 if (ret < state->vector.iov_len) {
3287 uint8_t *base;
3288 base = (uint8_t *)state->vector.iov_base;
3289 base += ret;
3290 state->vector.iov_base = (void *)base;
3291 state->vector.iov_len -= ret;
3292 /* we have more to read */
3293 TEVENT_FD_READABLE(xconn->transport.fde);
3294 return NT_STATUS_OK;
3297 if (state->pktlen > 0) {
3298 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3300 * Not a possible receivefile write.
3301 * Read the rest of the data.
3303 state->doing_receivefile = false;
3305 state->pktbuf = talloc_realloc(state->req,
3306 state->pktbuf,
3307 uint8_t,
3308 state->pktfull);
3309 if (state->pktbuf == NULL) {
3310 return NT_STATUS_NO_MEMORY;
3313 state->vector.iov_base = (void *)(state->pktbuf +
3314 state->pktlen);
3315 state->vector.iov_len = (state->pktfull -
3316 state->pktlen);
3318 state->pktlen = state->pktfull;
3319 goto again;
3323 * Either this is a receivefile write so we've
3324 * done a short read, or if not we have all the data.
3326 goto got_full;
3330 * Now we analyze the NBT header
3332 if (state->hdr.nbt[0] != 0x00) {
3333 state->min_recv_size = 0;
3335 state->pktfull = smb2_len(state->hdr.nbt);
3336 if (state->pktfull == 0) {
3337 goto got_full;
3340 if (state->min_recv_size != 0) {
3341 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3342 min_recvfile_size += state->min_recv_size;
3345 if (state->pktfull > min_recvfile_size) {
3347 * Might be a receivefile write. Read the SMB2 HEADER +
3348 * SMB2_WRITE header first. Set 'doing_receivefile'
3349 * as we're *attempting* receivefile write. If this
3350 * turns out not to be a SMB2_WRITE request or otherwise
3351 * not suitable then we'll just read the rest of the data
3352 * the next time this function is called.
3354 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3355 state->doing_receivefile = true;
3356 } else {
3357 state->pktlen = state->pktfull;
3360 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3361 if (state->pktbuf == NULL) {
3362 return NT_STATUS_NO_MEMORY;
3365 state->vector.iov_base = (void *)state->pktbuf;
3366 state->vector.iov_len = state->pktlen;
3368 goto again;
3370 got_full:
3372 if (state->hdr.nbt[0] != 0x00) {
3373 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3374 state->hdr.nbt[0]));
3376 req = state->req;
3377 ZERO_STRUCTP(state);
3378 state->req = req;
3379 state->min_recv_size = lp_min_receive_file_size();
3380 req = NULL;
3381 goto again;
3384 req = state->req;
3385 state->req = NULL;
3387 req->request_time = timeval_current();
3388 now = timeval_to_nttime(&req->request_time);
3390 status = smbd_smb2_inbuf_parse_compound(xconn,
3391 now,
3392 state->pktbuf,
3393 state->pktlen,
3394 req,
3395 &req->in.vector,
3396 &req->in.vector_count);
3397 if (!NT_STATUS_IS_OK(status)) {
3398 return status;
3401 if (state->doing_receivefile) {
3402 req->smb1req = talloc_zero(req, struct smb_request);
3403 if (req->smb1req == NULL) {
3404 return NT_STATUS_NO_MEMORY;
3406 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3409 ZERO_STRUCTP(state);
3411 req->current_idx = 1;
3413 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3414 req->current_idx, req->in.vector_count));
3416 status = smbd_smb2_request_validate(req);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 return status;
3421 status = smbd_smb2_request_setup_out(req);
3422 if (!NT_STATUS_IS_OK(status)) {
3423 return status;
3426 status = smbd_smb2_request_dispatch(req);
3427 if (!NT_STATUS_IS_OK(status)) {
3428 return status;
3431 sconn->num_requests++;
3433 /* The timeout_processing function isn't run nearly
3434 often enough to implement 'max log size' without
3435 overrunning the size of the file by many megabytes.
3436 This is especially true if we are running at debug
3437 level 10. Checking every 50 SMB2s is a nice
3438 tradeoff of performance vs log file size overrun. */
3440 if ((sconn->num_requests % 50) == 0 &&
3441 need_to_check_log_size()) {
3442 change_to_root_user();
3443 check_log_size();
3446 status = smbd_smb2_request_next_incoming(xconn);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 return status;
3451 return NT_STATUS_OK;
3454 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3455 struct tevent_fd *fde,
3456 uint16_t flags,
3457 void *private_data)
3459 struct smbXsrv_connection *xconn =
3460 talloc_get_type_abort(private_data,
3461 struct smbXsrv_connection);
3462 NTSTATUS status;
3464 status = smbd_smb2_io_handler(xconn, flags);
3465 if (!NT_STATUS_IS_OK(status)) {
3466 smbd_server_connection_terminate(xconn, nt_errstr(status));
3467 return;