printer_list: fix talloc tos leak of tdb record
[Samba.git] / source3 / smbd / smb2_server.c
blob710020878037e205a595612ef1505c43e9fc13d7
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
35 uint16_t flags,
36 void *private_data);
37 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
39 static const struct smbd_smb2_dispatch_table {
40 uint16_t opcode;
41 const char *name;
42 bool need_session;
43 bool need_tcon;
44 bool as_root;
45 uint16_t fileid_ofs;
46 bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
50 _OP(SMB2_OP_NEGPROT),
51 .as_root = true,
52 },{
53 _OP(SMB2_OP_SESSSETUP),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_LOGOFF),
57 .need_session = true,
58 .as_root = true,
59 },{
60 _OP(SMB2_OP_TCON),
61 .need_session = true,
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
69 .as_root = true,
70 },{
71 _OP(SMB2_OP_TDIS),
72 .need_session = true,
73 .need_tcon = true,
74 .as_root = true,
75 },{
76 _OP(SMB2_OP_CREATE),
77 .need_session = true,
78 .need_tcon = true,
79 },{
80 _OP(SMB2_OP_CLOSE),
81 .need_session = true,
82 .need_tcon = true,
83 .fileid_ofs = 0x08,
84 },{
85 _OP(SMB2_OP_FLUSH),
86 .need_session = true,
87 .need_tcon = true,
88 .fileid_ofs = 0x08,
89 },{
90 _OP(SMB2_OP_READ),
91 .need_session = true,
92 .need_tcon = true,
93 .fileid_ofs = 0x10,
94 },{
95 _OP(SMB2_OP_WRITE),
96 .need_session = true,
97 .need_tcon = true,
98 .fileid_ofs = 0x10,
99 },{
100 _OP(SMB2_OP_LOCK),
101 .need_session = true,
102 .need_tcon = true,
103 .fileid_ofs = 0x08,
105 _OP(SMB2_OP_IOCTL),
106 .need_session = true,
107 .need_tcon = true,
108 .fileid_ofs = 0x08,
109 .allow_invalid_fileid = true,
111 _OP(SMB2_OP_CANCEL),
112 .as_root = true,
114 _OP(SMB2_OP_KEEPALIVE),
115 .as_root = true,
117 _OP(SMB2_OP_FIND),
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x08,
122 _OP(SMB2_OP_NOTIFY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_GETINFO),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x18,
132 _OP(SMB2_OP_SETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x10,
137 _OP(SMB2_OP_BREAK),
138 .need_session = true,
139 .need_tcon = true,
141 * we do not set
142 * .fileid_ofs here
143 * as LEASE breaks does not
144 * have a file id
149 const char *smb2_opcode_name(uint16_t opcode)
151 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table[opcode].name;
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 const struct smbd_smb2_dispatch_table *ret = NULL;
161 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
162 return NULL;
165 ret = &smbd_smb2_table[opcode];
167 SMB_ASSERT(ret->opcode == opcode);
169 return ret;
172 static void print_req_vectors(const struct smbd_smb2_request *req)
174 int i;
176 for (i = 0; i < req->in.vector_count; i++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
178 (unsigned int)i,
179 (unsigned int)req->in.vector[i].iov_len);
181 for (i = 0; i < req->out.vector_count; i++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
183 (unsigned int)i,
184 (unsigned int)req->out.vector[i].iov_len);
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 if (size < (4 + SMB2_HDR_BODY)) {
191 return false;
194 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
195 return false;
198 return true;
201 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
203 TALLOC_FREE(xconn->transport.fde);
205 xconn->smb2.credits.seq_low = 0;
206 xconn->smb2.credits.seq_range = 1;
207 xconn->smb2.credits.granted = 1;
208 xconn->smb2.credits.max = lp_smb2_max_credits();
209 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
210 xconn->smb2.credits.max);
211 if (xconn->smb2.credits.bitmap == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
216 xconn,
217 xconn->transport.sock,
218 TEVENT_FD_READ,
219 smbd_smb2_connection_handler,
220 xconn);
221 if (xconn->transport.fde == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* Ensure child is set to non-blocking mode */
226 set_blocking(xconn->transport.sock, false);
227 return NT_STATUS_OK;
230 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
231 #define _smb2_setlen(_buf,len) do { \
232 uint8_t *buf = (uint8_t *)_buf; \
233 buf[0] = 0; \
234 buf[1] = ((len)&0xFF0000)>>16; \
235 buf[2] = ((len)&0xFF00)>>8; \
236 buf[3] = (len)&0xFF; \
237 } while (0)
239 static void smb2_setup_nbt_length(struct iovec *vector, int count)
241 size_t len = 0;
242 int i;
244 for (i=1; i < count; i++) {
245 len += vector[i].iov_len;
248 _smb2_setlen(vector[0].iov_base, len);
251 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
253 if (req->first_key.length > 0) {
254 data_blob_clear_free(&req->first_key);
256 if (req->last_key.length > 0) {
257 data_blob_clear_free(&req->last_key);
259 return 0;
262 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
264 TALLOC_CTX *mem_pool;
265 struct smbd_smb2_request *req;
267 #if 0
268 /* Enable this to find subtle valgrind errors. */
269 mem_pool = talloc_init("smbd_smb2_request_allocate");
270 #else
271 mem_pool = talloc_tos();
272 #endif
273 if (mem_pool == NULL) {
274 return NULL;
277 req = talloc_zero(mem_pool, struct smbd_smb2_request);
278 if (req == NULL) {
279 talloc_free(mem_pool);
280 return NULL;
282 talloc_reparent(mem_pool, mem_ctx, req);
283 #if 0
284 TALLOC_FREE(mem_pool);
285 #endif
287 req->last_session_id = UINT64_MAX;
288 req->last_tid = UINT32_MAX;
290 talloc_set_destructor(req, smbd_smb2_request_destructor);
292 return req;
295 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
296 NTTIME now,
297 uint8_t *buf,
298 size_t buflen,
299 struct smbd_smb2_request *req,
300 struct iovec **piov,
301 int *pnum_iov)
303 TALLOC_CTX *mem_ctx = req;
304 struct iovec *iov;
305 int num_iov = 1;
306 size_t taken = 0;
307 uint8_t *first_hdr = buf;
308 size_t verified_buflen = 0;
309 uint8_t *tf = NULL;
310 size_t tf_len = 0;
313 * Note: index '0' is reserved for the transport protocol
315 iov = req->in._vector;
317 while (taken < buflen) {
318 size_t len = buflen - taken;
319 uint8_t *hdr = first_hdr + taken;
320 struct iovec *cur;
321 size_t full_size;
322 size_t next_command_ofs;
323 uint16_t body_size;
324 uint8_t *body = NULL;
325 uint32_t dyn_size;
326 uint8_t *dyn = NULL;
327 struct iovec *iov_alloc = NULL;
329 if (iov != req->in._vector) {
330 iov_alloc = iov;
333 if (verified_buflen > taken) {
334 len = verified_buflen - taken;
335 } else {
336 tf = NULL;
337 tf_len = 0;
340 if (len < 4) {
341 DEBUG(10, ("%d bytes left, expected at least %d\n",
342 (int)len, 4));
343 goto inval;
345 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
346 struct smbXsrv_session *s = NULL;
347 uint64_t uid;
348 struct iovec tf_iov[2];
349 NTSTATUS status;
350 size_t enc_len;
352 if (xconn->protocol < PROTOCOL_SMB2_24) {
353 DEBUG(10, ("Got SMB2_TRANSFORM header, "
354 "but dialect[0x%04X] is used\n",
355 xconn->smb2.server.dialect));
356 goto inval;
359 if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but not negotiated "
362 "client[0x%08X] server[0x%08X]\n",
363 xconn->smb2.client.capabilities,
364 xconn->smb2.server.capabilities));
365 goto inval;
368 if (len < SMB2_TF_HDR_SIZE) {
369 DEBUG(1, ("%d bytes left, expected at least %d\n",
370 (int)len, SMB2_TF_HDR_SIZE));
371 goto inval;
373 tf = hdr;
374 tf_len = SMB2_TF_HDR_SIZE;
375 taken += tf_len;
377 hdr = first_hdr + taken;
378 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
379 uid = BVAL(tf, SMB2_TF_SESSION_ID);
381 if (len < SMB2_TF_HDR_SIZE + enc_len) {
382 DEBUG(1, ("%d bytes left, expected at least %d\n",
383 (int)len,
384 (int)(SMB2_TF_HDR_SIZE + enc_len)));
385 goto inval;
388 status = smb2srv_session_lookup(xconn, uid, now, &s);
389 if (s == NULL) {
390 DEBUG(1, ("invalid session[%llu] in "
391 "SMB2_TRANSFORM header\n",
392 (unsigned long long)uid));
393 TALLOC_FREE(iov_alloc);
394 return NT_STATUS_USER_SESSION_DELETED;
397 tf_iov[0].iov_base = (void *)tf;
398 tf_iov[0].iov_len = tf_len;
399 tf_iov[1].iov_base = (void *)hdr;
400 tf_iov[1].iov_len = enc_len;
402 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
403 xconn->protocol,
404 tf_iov, 2);
405 if (!NT_STATUS_IS_OK(status)) {
406 TALLOC_FREE(iov_alloc);
407 return status;
410 verified_buflen = taken + enc_len;
411 len = enc_len;
415 * We need the header plus the body length field
418 if (len < SMB2_HDR_BODY + 2) {
419 DEBUG(10, ("%d bytes left, expected at least %d\n",
420 (int)len, SMB2_HDR_BODY));
421 goto inval;
423 if (IVAL(hdr, 0) != SMB2_MAGIC) {
424 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
425 IVAL(hdr, 0)));
426 goto inval;
428 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
429 DEBUG(10, ("Got HDR len %d, expected %d\n",
430 SVAL(hdr, 4), SMB2_HDR_BODY));
431 goto inval;
434 full_size = len;
435 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
436 body_size = SVAL(hdr, SMB2_HDR_BODY);
438 if (next_command_ofs != 0) {
439 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
440 goto inval;
442 if (next_command_ofs > full_size) {
443 goto inval;
445 full_size = next_command_ofs;
447 if (body_size < 2) {
448 goto inval;
450 body_size &= 0xfffe;
452 if (body_size > (full_size - SMB2_HDR_BODY)) {
454 * let the caller handle the error
456 body_size = full_size - SMB2_HDR_BODY;
458 body = hdr + SMB2_HDR_BODY;
459 dyn = body + body_size;
460 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
462 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
463 struct iovec *iov_tmp = NULL;
465 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
466 struct iovec,
467 num_iov +
468 SMBD_SMB2_NUM_IOV_PER_REQ);
469 if (iov_tmp == NULL) {
470 TALLOC_FREE(iov_alloc);
471 return NT_STATUS_NO_MEMORY;
474 if (iov_alloc == NULL) {
475 memcpy(iov_tmp,
476 req->in._vector,
477 sizeof(req->in._vector));
480 iov = iov_tmp;
482 cur = &iov[num_iov];
483 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
485 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
486 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
487 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
488 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
489 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
490 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
491 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
492 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
494 taken += full_size;
497 *piov = iov;
498 *pnum_iov = num_iov;
499 return NT_STATUS_OK;
501 inval:
502 if (iov != req->in._vector) {
503 TALLOC_FREE(iov);
505 return NT_STATUS_INVALID_PARAMETER;
508 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
509 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->protocol,
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->protocol,
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 /* TODO: verify more things */
1950 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1951 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1952 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1953 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1954 smb2_opcode_name(opcode),
1955 (unsigned long long)mid));
1957 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1959 * once the protocol is negotiated
1960 * SMB2_OP_NEGPROT is not allowed anymore
1962 if (opcode == SMB2_OP_NEGPROT) {
1963 /* drop the connection */
1964 return NT_STATUS_INVALID_PARAMETER;
1966 } else {
1968 * if the protocol is not negotiated yet
1969 * only SMB2_OP_NEGPROT is allowed.
1971 if (opcode != SMB2_OP_NEGPROT) {
1972 /* drop the connection */
1973 return NT_STATUS_INVALID_PARAMETER;
1978 * Check if the client provided a valid session id,
1979 * if so smbd_smb2_request_check_session() calls
1980 * set_current_user_info().
1982 * As some command don't require a valid session id
1983 * we defer the check of the session_status
1985 session_status = smbd_smb2_request_check_session(req);
1986 x = req->session;
1987 if (x != NULL) {
1988 signing_required = x->global->signing_required;
1989 encryption_required = x->global->encryption_required;
1991 if (opcode == SMB2_OP_SESSSETUP &&
1992 x->global->signing_key.length > 0) {
1993 signing_required = true;
1997 req->do_signing = false;
1998 req->do_encryption = false;
1999 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2000 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2001 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2003 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2004 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2005 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2006 (unsigned long long)x->global->session_wire_id,
2007 (unsigned long long)tf_session_id));
2009 * TODO: windows allows this...
2010 * should we drop the connection?
2012 * For now we just return ACCESS_DENIED
2013 * (Windows clients never trigger this)
2014 * and wait for an update of [MS-SMB2].
2016 return smbd_smb2_request_error(req,
2017 NT_STATUS_ACCESS_DENIED);
2020 req->do_encryption = true;
2023 if (encryption_required && !req->do_encryption) {
2024 return smbd_smb2_request_error(req,
2025 NT_STATUS_ACCESS_DENIED);
2028 call = smbd_smb2_call(opcode);
2029 if (call == NULL) {
2030 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2033 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2034 SMB2_HDR_FLAG_SIGNED |
2035 SMB2_HDR_FLAG_DFS;
2036 if (opcode == SMB2_OP_CANCEL) {
2037 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2039 if ((flags & ~allowed_flags) != 0) {
2040 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2043 if (flags & SMB2_HDR_FLAG_CHAINED) {
2045 * This check is mostly for giving the correct error code
2046 * for compounded requests.
2048 if (!NT_STATUS_IS_OK(session_status)) {
2049 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2051 } else {
2052 req->compat_chain_fsp = NULL;
2055 if (req->do_encryption) {
2056 signing_required = false;
2057 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2058 DATA_BLOB signing_key = data_blob_null;
2060 if (x == NULL) {
2062 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2063 * If the SMB2 header of the SMB2 NEGOTIATE
2064 * request has the SMB2_FLAGS_SIGNED bit set in the
2065 * Flags field, the server MUST fail the request
2066 * with STATUS_INVALID_PARAMETER.
2068 * Microsoft test tool checks this.
2071 if ((opcode == SMB2_OP_NEGPROT) &&
2072 (flags & SMB2_HDR_FLAG_SIGNED)) {
2073 status = NT_STATUS_INVALID_PARAMETER;
2074 } else {
2075 status = NT_STATUS_USER_SESSION_DELETED;
2077 return smbd_smb2_request_error(req, status);
2080 signing_key = smbd_smb2_signing_key(x, xconn);
2083 * If we have a signing key, we should
2084 * sign the response
2086 if (signing_key.length > 0) {
2087 req->do_signing = true;
2090 status = smb2_signing_check_pdu(signing_key,
2091 xconn->protocol,
2092 SMBD_SMB2_IN_HDR_IOV(req),
2093 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 return smbd_smb2_request_error(req, status);
2099 * Now that we know the request was correctly signed
2100 * we have to sign the response too.
2102 req->do_signing = true;
2104 if (!NT_STATUS_IS_OK(session_status)) {
2105 return smbd_smb2_request_error(req, session_status);
2107 } else if (opcode == SMB2_OP_CANCEL) {
2108 /* Cancel requests are allowed to skip the signing */
2109 } else if (signing_required) {
2111 * If signing is required we try to sign
2112 * a possible error response
2114 req->do_signing = true;
2115 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2118 if (flags & SMB2_HDR_FLAG_CHAINED) {
2119 req->compound_related = true;
2122 if (call->need_session) {
2123 if (!NT_STATUS_IS_OK(session_status)) {
2124 return smbd_smb2_request_error(req, session_status);
2128 if (call->need_tcon) {
2129 SMB_ASSERT(call->need_session);
2132 * This call needs to be run as user.
2134 * smbd_smb2_request_check_tcon()
2135 * calls change_to_user() on success.
2137 status = smbd_smb2_request_check_tcon(req);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 return smbd_smb2_request_error(req, status);
2141 if (req->tcon->global->encryption_required) {
2142 encryption_required = true;
2144 if (encryption_required && !req->do_encryption) {
2145 return smbd_smb2_request_error(req,
2146 NT_STATUS_ACCESS_DENIED);
2150 if (call->fileid_ofs != 0) {
2151 size_t needed = call->fileid_ofs + 16;
2152 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2153 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2154 uint64_t file_id_persistent;
2155 uint64_t file_id_volatile;
2156 struct files_struct *fsp;
2158 SMB_ASSERT(call->need_tcon);
2160 if (needed > body_size) {
2161 return smbd_smb2_request_error(req,
2162 NT_STATUS_INVALID_PARAMETER);
2165 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2166 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2168 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2169 if (fsp == NULL) {
2170 if (!call->allow_invalid_fileid) {
2171 return smbd_smb2_request_error(req,
2172 NT_STATUS_FILE_CLOSED);
2175 if (file_id_persistent != UINT64_MAX) {
2176 return smbd_smb2_request_error(req,
2177 NT_STATUS_FILE_CLOSED);
2179 if (file_id_volatile != UINT64_MAX) {
2180 return smbd_smb2_request_error(req,
2181 NT_STATUS_FILE_CLOSED);
2186 if (call->as_root) {
2187 SMB_ASSERT(call->fileid_ofs == 0);
2188 /* This call needs to be run as root */
2189 change_to_root_user();
2190 } else {
2191 SMB_ASSERT(call->need_tcon);
2194 switch (opcode) {
2195 case SMB2_OP_NEGPROT:
2197 START_PROFILE(smb2_negprot);
2198 return_value = smbd_smb2_request_process_negprot(req);
2199 END_PROFILE(smb2_negprot);
2201 break;
2203 case SMB2_OP_SESSSETUP:
2205 START_PROFILE(smb2_sesssetup);
2206 return_value = smbd_smb2_request_process_sesssetup(req);
2207 END_PROFILE(smb2_sesssetup);
2209 break;
2211 case SMB2_OP_LOGOFF:
2213 START_PROFILE(smb2_logoff);
2214 return_value = smbd_smb2_request_process_logoff(req);
2215 END_PROFILE(smb2_logoff);
2217 break;
2219 case SMB2_OP_TCON:
2221 START_PROFILE(smb2_tcon);
2222 return_value = smbd_smb2_request_process_tcon(req);
2223 END_PROFILE(smb2_tcon);
2225 break;
2227 case SMB2_OP_TDIS:
2229 START_PROFILE(smb2_tdis);
2230 return_value = smbd_smb2_request_process_tdis(req);
2231 END_PROFILE(smb2_tdis);
2233 break;
2235 case SMB2_OP_CREATE:
2237 START_PROFILE(smb2_create);
2238 return_value = smbd_smb2_request_process_create(req);
2239 END_PROFILE(smb2_create);
2241 break;
2243 case SMB2_OP_CLOSE:
2245 START_PROFILE(smb2_close);
2246 return_value = smbd_smb2_request_process_close(req);
2247 END_PROFILE(smb2_close);
2249 break;
2251 case SMB2_OP_FLUSH:
2253 START_PROFILE(smb2_flush);
2254 return_value = smbd_smb2_request_process_flush(req);
2255 END_PROFILE(smb2_flush);
2257 break;
2259 case SMB2_OP_READ:
2261 START_PROFILE(smb2_read);
2262 return_value = smbd_smb2_request_process_read(req);
2263 END_PROFILE(smb2_read);
2265 break;
2267 case SMB2_OP_WRITE:
2269 START_PROFILE(smb2_write);
2270 return_value = smbd_smb2_request_process_write(req);
2271 END_PROFILE(smb2_write);
2273 break;
2275 case SMB2_OP_LOCK:
2277 START_PROFILE(smb2_lock);
2278 return_value = smbd_smb2_request_process_lock(req);
2279 END_PROFILE(smb2_lock);
2281 break;
2283 case SMB2_OP_IOCTL:
2285 START_PROFILE(smb2_ioctl);
2286 return_value = smbd_smb2_request_process_ioctl(req);
2287 END_PROFILE(smb2_ioctl);
2289 break;
2291 case SMB2_OP_CANCEL:
2293 START_PROFILE(smb2_cancel);
2294 return_value = smbd_smb2_request_process_cancel(req);
2295 END_PROFILE(smb2_cancel);
2297 break;
2299 case SMB2_OP_KEEPALIVE:
2301 START_PROFILE(smb2_keepalive);
2302 return_value = smbd_smb2_request_process_keepalive(req);
2303 END_PROFILE(smb2_keepalive);
2305 break;
2307 case SMB2_OP_FIND:
2309 START_PROFILE(smb2_find);
2310 return_value = smbd_smb2_request_process_find(req);
2311 END_PROFILE(smb2_find);
2313 break;
2315 case SMB2_OP_NOTIFY:
2317 START_PROFILE(smb2_notify);
2318 return_value = smbd_smb2_request_process_notify(req);
2319 END_PROFILE(smb2_notify);
2321 break;
2323 case SMB2_OP_GETINFO:
2325 START_PROFILE(smb2_getinfo);
2326 return_value = smbd_smb2_request_process_getinfo(req);
2327 END_PROFILE(smb2_getinfo);
2329 break;
2331 case SMB2_OP_SETINFO:
2333 START_PROFILE(smb2_setinfo);
2334 return_value = smbd_smb2_request_process_setinfo(req);
2335 END_PROFILE(smb2_setinfo);
2337 break;
2339 case SMB2_OP_BREAK:
2341 START_PROFILE(smb2_break);
2342 return_value = smbd_smb2_request_process_break(req);
2343 END_PROFILE(smb2_break);
2345 break;
2347 default:
2348 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2349 break;
2351 return return_value;
2354 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2356 struct smbXsrv_connection *xconn = req->xconn;
2357 int first_idx = 1;
2358 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2359 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2360 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2361 NTSTATUS status;
2363 req->subreq = NULL;
2364 TALLOC_FREE(req->async_te);
2366 if (req->do_encryption &&
2367 (firsttf->iov_len == 0) &&
2368 (req->first_key.length == 0) &&
2369 (req->session != NULL) &&
2370 (req->session->global->encryption_key.length != 0))
2372 DATA_BLOB encryption_key = req->session->global->encryption_key;
2373 uint8_t *tf;
2374 uint64_t session_id = req->session->global->session_wire_id;
2375 struct smbXsrv_session *x = req->session;
2376 uint64_t nonce_high;
2377 uint64_t nonce_low;
2379 nonce_high = x->nonce_high;
2380 nonce_low = x->nonce_low;
2382 x->nonce_low += 1;
2383 if (x->nonce_low == 0) {
2384 x->nonce_low += 1;
2385 x->nonce_high += 1;
2389 * We need to place the SMB2_TRANSFORM header before the
2390 * first SMB2 header
2394 * we need to remember the encryption key
2395 * and defer the signing/encryption until
2396 * we are sure that we do not change
2397 * the header again.
2399 req->first_key = data_blob_dup_talloc(req, encryption_key);
2400 if (req->first_key.data == NULL) {
2401 return NT_STATUS_NO_MEMORY;
2404 tf = talloc_zero_array(req, uint8_t,
2405 SMB2_TF_HDR_SIZE);
2406 if (tf == NULL) {
2407 return NT_STATUS_NO_MEMORY;
2410 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2411 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2412 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2413 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2415 firsttf->iov_base = (void *)tf;
2416 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2419 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2420 (req->last_key.length > 0) &&
2421 (firsttf->iov_len == 0))
2423 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2424 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2427 * As we are sure the header of the last request in the
2428 * compound chain will not change, we can to sign here
2429 * with the last signing key we remembered.
2431 status = smb2_signing_sign_pdu(req->last_key,
2432 xconn->protocol,
2433 lasthdr,
2434 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2435 if (!NT_STATUS_IS_OK(status)) {
2436 return status;
2439 if (req->last_key.length > 0) {
2440 data_blob_clear_free(&req->last_key);
2443 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2445 if (req->current_idx < req->out.vector_count) {
2447 * We must process the remaining compound
2448 * SMB2 requests before any new incoming SMB2
2449 * requests. This is because incoming SMB2
2450 * requests may include a cancel for a
2451 * compound request we haven't processed
2452 * yet.
2454 struct tevent_immediate *im = tevent_create_immediate(req);
2455 if (!im) {
2456 return NT_STATUS_NO_MEMORY;
2459 if (req->do_signing && firsttf->iov_len == 0) {
2460 struct smbXsrv_session *x = req->session;
2461 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2464 * we need to remember the signing key
2465 * and defer the signing until
2466 * we are sure that we do not change
2467 * the header again.
2469 req->last_key = data_blob_dup_talloc(req, signing_key);
2470 if (req->last_key.data == NULL) {
2471 return NT_STATUS_NO_MEMORY;
2475 tevent_schedule_immediate(im,
2476 req->sconn->ev_ctx,
2477 smbd_smb2_request_dispatch_immediate,
2478 req);
2479 return NT_STATUS_OK;
2482 if (req->compound_related) {
2483 req->compound_related = false;
2486 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2488 /* Set credit for these operations (zero credits if this
2489 is a final reply for an async operation). */
2490 smb2_calculate_credits(req, req);
2493 * now check if we need to sign the current response
2495 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2496 status = smb2_signing_encrypt_pdu(req->first_key,
2497 xconn->protocol,
2498 firsttf,
2499 req->out.vector_count - first_idx);
2500 if (!NT_STATUS_IS_OK(status)) {
2501 return status;
2503 } else if (req->do_signing) {
2504 struct smbXsrv_session *x = req->session;
2505 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2507 status = smb2_signing_sign_pdu(signing_key,
2508 xconn->protocol,
2509 outhdr,
2510 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 return status;
2515 if (req->first_key.length > 0) {
2516 data_blob_clear_free(&req->first_key);
2519 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2520 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2521 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2522 /* Dynamic part is NULL. Chop it off,
2523 We're going to send it via sendfile. */
2524 req->out.vector_count -= 1;
2528 * We're done with this request -
2529 * move it off the "being processed" queue.
2531 DLIST_REMOVE(xconn->smb2.requests, req);
2533 req->queue_entry.mem_ctx = req;
2534 req->queue_entry.vector = req->out.vector;
2535 req->queue_entry.count = req->out.vector_count;
2536 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2537 xconn->smb2.send_queue_len++;
2539 status = smbd_smb2_flush_send_queue(xconn);
2540 if (!NT_STATUS_IS_OK(status)) {
2541 return status;
2544 return NT_STATUS_OK;
2547 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2549 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2550 struct tevent_immediate *im,
2551 void *private_data)
2553 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2554 struct smbd_smb2_request);
2555 struct smbXsrv_connection *xconn = req->xconn;
2556 NTSTATUS status;
2558 TALLOC_FREE(im);
2560 if (DEBUGLEVEL >= 10) {
2561 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2562 req->current_idx, req->in.vector_count));
2563 print_req_vectors(req);
2566 status = smbd_smb2_request_dispatch(req);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 smbd_server_connection_terminate(xconn, nt_errstr(status));
2569 return;
2572 status = smbd_smb2_request_next_incoming(xconn);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 smbd_server_connection_terminate(xconn, nt_errstr(status));
2575 return;
2579 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2580 NTSTATUS status,
2581 DATA_BLOB body, DATA_BLOB *dyn,
2582 const char *location)
2584 uint8_t *outhdr;
2585 struct iovec *outbody_v;
2586 struct iovec *outdyn_v;
2587 uint32_t next_command_ofs;
2589 DEBUG(10,("smbd_smb2_request_done_ex: "
2590 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2591 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2592 dyn ? "yes": "no",
2593 (unsigned int)(dyn ? dyn->length : 0),
2594 location));
2596 if (body.length < 2) {
2597 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2600 if ((body.length % 2) != 0) {
2601 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2604 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2605 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2606 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2608 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2609 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2611 outbody_v->iov_base = (void *)body.data;
2612 outbody_v->iov_len = body.length;
2614 if (dyn) {
2615 outdyn_v->iov_base = (void *)dyn->data;
2616 outdyn_v->iov_len = dyn->length;
2617 } else {
2618 outdyn_v->iov_base = NULL;
2619 outdyn_v->iov_len = 0;
2622 /* see if we need to recalculate the offset to the next response */
2623 if (next_command_ofs > 0) {
2624 next_command_ofs = SMB2_HDR_BODY;
2625 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2626 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2629 if ((next_command_ofs % 8) != 0) {
2630 size_t pad_size = 8 - (next_command_ofs % 8);
2631 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2633 * if the dyn buffer is empty
2634 * we can use it to add padding
2636 uint8_t *pad;
2638 pad = talloc_zero_array(req,
2639 uint8_t, pad_size);
2640 if (pad == NULL) {
2641 return smbd_smb2_request_error(req,
2642 NT_STATUS_NO_MEMORY);
2645 outdyn_v->iov_base = (void *)pad;
2646 outdyn_v->iov_len = pad_size;
2647 } else {
2649 * For now we copy the dynamic buffer
2650 * and add the padding to the new buffer
2652 size_t old_size;
2653 uint8_t *old_dyn;
2654 size_t new_size;
2655 uint8_t *new_dyn;
2657 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2658 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2660 new_size = old_size + pad_size;
2661 new_dyn = talloc_zero_array(req,
2662 uint8_t, new_size);
2663 if (new_dyn == NULL) {
2664 return smbd_smb2_request_error(req,
2665 NT_STATUS_NO_MEMORY);
2668 memcpy(new_dyn, old_dyn, old_size);
2669 memset(new_dyn + old_size, 0, pad_size);
2671 outdyn_v->iov_base = (void *)new_dyn;
2672 outdyn_v->iov_len = new_size;
2674 next_command_ofs += pad_size;
2677 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2679 return smbd_smb2_request_reply(req);
2682 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2683 NTSTATUS status,
2684 DATA_BLOB *info,
2685 const char *location)
2687 struct smbXsrv_connection *xconn = req->xconn;
2688 DATA_BLOB body;
2689 DATA_BLOB _dyn;
2690 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2691 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2693 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2694 req->current_idx, nt_errstr(status), info ? " +info" : "",
2695 location));
2697 if (unread_bytes) {
2698 /* Recvfile error. Drain incoming socket. */
2699 size_t ret;
2701 errno = 0;
2702 ret = drain_socket(xconn->transport.sock, unread_bytes);
2703 if (ret != unread_bytes) {
2704 NTSTATUS error;
2706 if (errno == 0) {
2707 error = NT_STATUS_IO_DEVICE_ERROR;
2708 } else {
2709 error = map_nt_error_from_unix_common(errno);
2712 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2713 "ret[%u] errno[%d] => %s\n",
2714 (unsigned)unread_bytes,
2715 (unsigned)ret, errno, nt_errstr(error)));
2716 return error;
2720 body.data = outhdr + SMB2_HDR_BODY;
2721 body.length = 8;
2722 SSVAL(body.data, 0, 9);
2724 if (info) {
2725 SIVAL(body.data, 0x04, info->length);
2726 } else {
2727 /* Allocated size of req->out.vector[i].iov_base
2728 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2729 * 1 byte without having to do an alloc.
2731 info = &_dyn;
2732 info->data = ((uint8_t *)outhdr) +
2733 OUTVEC_ALLOC_SIZE - 1;
2734 info->length = 1;
2735 SCVAL(info->data, 0, 0);
2739 * Note: Even if there is an error, continue to process the request.
2740 * per MS-SMB2.
2743 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2747 struct smbd_smb2_send_break_state {
2748 struct smbd_smb2_send_queue queue_entry;
2749 uint8_t nbt_hdr[NBT_HDR_SIZE];
2750 uint8_t tf[SMB2_TF_HDR_SIZE];
2751 uint8_t hdr[SMB2_HDR_BODY];
2752 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2753 uint8_t body[1];
2756 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2757 struct smbXsrv_session *session,
2758 struct smbXsrv_tcon *tcon,
2759 const uint8_t *body,
2760 size_t body_len)
2762 struct smbd_smb2_send_break_state *state;
2763 bool do_encryption = session->global->encryption_required;
2764 uint64_t nonce_high = 0;
2765 uint64_t nonce_low = 0;
2766 NTSTATUS status;
2767 size_t statelen;
2769 if (tcon->global->encryption_required) {
2770 do_encryption = true;
2773 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2774 body_len;
2776 state = talloc_zero_size(xconn, statelen);
2777 if (state == NULL) {
2778 return NT_STATUS_NO_MEMORY;
2780 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2782 if (do_encryption) {
2783 nonce_high = session->nonce_high;
2784 nonce_low = session->nonce_low;
2786 session->nonce_low += 1;
2787 if (session->nonce_low == 0) {
2788 session->nonce_low += 1;
2789 session->nonce_high += 1;
2793 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2794 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2795 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2796 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2798 SIVAL(state->hdr, 0, SMB2_MAGIC);
2799 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2800 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2801 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2802 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2803 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2804 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2805 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2806 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2807 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2808 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2809 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2810 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2812 state->vector[0] = (struct iovec) {
2813 .iov_base = state->nbt_hdr,
2814 .iov_len = sizeof(state->nbt_hdr)
2817 if (do_encryption) {
2818 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2819 .iov_base = state->tf,
2820 .iov_len = sizeof(state->tf)
2822 } else {
2823 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2824 .iov_base = NULL,
2825 .iov_len = 0
2829 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2830 .iov_base = state->hdr,
2831 .iov_len = sizeof(state->hdr)
2834 memcpy(state->body, body, body_len);
2836 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2837 .iov_base = state->body,
2838 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2842 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2845 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2847 if (do_encryption) {
2848 DATA_BLOB encryption_key = session->global->encryption_key;
2850 status = smb2_signing_encrypt_pdu(encryption_key,
2851 xconn->protocol,
2852 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2853 SMBD_SMB2_NUM_IOV_PER_REQ);
2854 if (!NT_STATUS_IS_OK(status)) {
2855 return status;
2859 state->queue_entry.mem_ctx = state;
2860 state->queue_entry.vector = state->vector;
2861 state->queue_entry.count = ARRAY_SIZE(state->vector);
2862 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2863 xconn->smb2.send_queue_len++;
2865 status = smbd_smb2_flush_send_queue(xconn);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 return status;
2870 return NT_STATUS_OK;
2873 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2874 struct smbXsrv_session *session,
2875 struct smbXsrv_tcon *tcon,
2876 struct smbXsrv_open *op,
2877 uint8_t oplock_level)
2879 uint8_t body[0x18];
2881 SSVAL(body, 0x00, sizeof(body));
2882 SCVAL(body, 0x02, oplock_level);
2883 SCVAL(body, 0x03, 0); /* reserved */
2884 SIVAL(body, 0x04, 0); /* reserved */
2885 SBVAL(body, 0x08, op->global->open_persistent_id);
2886 SBVAL(body, 0x10, op->global->open_volatile_id);
2888 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2891 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2893 NTSTATUS status;
2894 uint32_t flags;
2895 uint64_t file_id_persistent;
2896 uint64_t file_id_volatile;
2897 struct smbXsrv_open *op = NULL;
2898 struct files_struct *fsp = NULL;
2899 const uint8_t *body = NULL;
2902 * This is only called with a pktbuf
2903 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2904 * bytes
2907 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2908 /* Transform header. Cannot recvfile. */
2909 return false;
2911 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2912 /* Not SMB2. Normal error path will cope. */
2913 return false;
2915 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2916 /* Not SMB2. Normal error path will cope. */
2917 return false;
2919 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2920 /* Needs to be a WRITE. */
2921 return false;
2923 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2924 /* Chained. Cannot recvfile. */
2925 return false;
2927 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2928 if (flags & SMB2_HDR_FLAG_CHAINED) {
2929 /* Chained. Cannot recvfile. */
2930 return false;
2932 if (flags & SMB2_HDR_FLAG_SIGNED) {
2933 /* Signed. Cannot recvfile. */
2934 return false;
2937 body = &state->pktbuf[SMB2_HDR_BODY];
2939 file_id_persistent = BVAL(body, 0x10);
2940 file_id_volatile = BVAL(body, 0x18);
2942 status = smb2srv_open_lookup(state->req->xconn,
2943 file_id_persistent,
2944 file_id_volatile,
2945 0, /* now */
2946 &op);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 return false;
2951 fsp = op->compat;
2952 if (fsp == NULL) {
2953 return false;
2955 if (fsp->conn == NULL) {
2956 return false;
2959 if (IS_IPC(fsp->conn)) {
2960 return false;
2962 if (IS_PRINT(fsp->conn)) {
2963 return false;
2966 DEBUG(10,("Doing recvfile write len = %u\n",
2967 (unsigned int)(state->pktfull - state->pktlen)));
2969 return true;
2972 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2974 struct smbd_server_connection *sconn = xconn->client->sconn;
2975 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2976 size_t max_send_queue_len;
2977 size_t cur_send_queue_len;
2979 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2981 * we're not supposed to do any io
2983 return NT_STATUS_OK;
2986 if (state->req != NULL) {
2988 * if there is already a tstream_readv_pdu
2989 * pending, we are done.
2991 return NT_STATUS_OK;
2994 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2995 cur_send_queue_len = xconn->smb2.send_queue_len;
2997 if (cur_send_queue_len > max_send_queue_len) {
2999 * if we have a lot of requests to send,
3000 * we wait until they are on the wire until we
3001 * ask for the next request.
3003 return NT_STATUS_OK;
3006 /* ask for the next request */
3007 ZERO_STRUCTP(state);
3008 state->req = smbd_smb2_request_allocate(xconn);
3009 if (state->req == NULL) {
3010 return NT_STATUS_NO_MEMORY;
3012 state->req->sconn = sconn;
3013 state->req->xconn = xconn;
3014 state->min_recv_size = lp_min_receive_file_size();
3016 TEVENT_FD_READABLE(xconn->transport.fde);
3018 return NT_STATUS_OK;
3021 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3022 const uint8_t *inpdu, size_t size)
3024 struct smbd_server_connection *sconn = xconn->client->sconn;
3025 NTSTATUS status;
3026 struct smbd_smb2_request *req = NULL;
3028 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3029 (unsigned int)size));
3031 status = smbd_initialize_smb2(xconn);
3032 if (!NT_STATUS_IS_OK(status)) {
3033 smbd_server_connection_terminate(xconn, nt_errstr(status));
3034 return;
3037 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3038 if (!NT_STATUS_IS_OK(status)) {
3039 smbd_server_connection_terminate(xconn, nt_errstr(status));
3040 return;
3043 status = smbd_smb2_request_validate(req);
3044 if (!NT_STATUS_IS_OK(status)) {
3045 smbd_server_connection_terminate(xconn, nt_errstr(status));
3046 return;
3049 status = smbd_smb2_request_setup_out(req);
3050 if (!NT_STATUS_IS_OK(status)) {
3051 smbd_server_connection_terminate(xconn, nt_errstr(status));
3052 return;
3055 status = smbd_smb2_request_dispatch(req);
3056 if (!NT_STATUS_IS_OK(status)) {
3057 smbd_server_connection_terminate(xconn, nt_errstr(status));
3058 return;
3061 status = smbd_smb2_request_next_incoming(xconn);
3062 if (!NT_STATUS_IS_OK(status)) {
3063 smbd_server_connection_terminate(xconn, nt_errstr(status));
3064 return;
3067 sconn->num_requests++;
3070 static int socket_error_from_errno(int ret,
3071 int sys_errno,
3072 bool *retry)
3074 *retry = false;
3076 if (ret >= 0) {
3077 return 0;
3080 if (ret != -1) {
3081 return EIO;
3084 if (sys_errno == 0) {
3085 return EIO;
3088 if (sys_errno == EINTR) {
3089 *retry = true;
3090 return sys_errno;
3093 if (sys_errno == EINPROGRESS) {
3094 *retry = true;
3095 return sys_errno;
3098 if (sys_errno == EAGAIN) {
3099 *retry = true;
3100 return sys_errno;
3103 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3104 if (sys_errno == ENOMEM) {
3105 *retry = true;
3106 return sys_errno;
3109 #ifdef EWOULDBLOCK
3110 #if EWOULDBLOCK != EAGAIN
3111 if (sys_errno == EWOULDBLOCK) {
3112 *retry = true;
3113 return sys_errno;
3115 #endif
3116 #endif
3118 return sys_errno;
3121 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3123 int ret;
3124 int err;
3125 bool retry;
3127 if (xconn->smb2.send_queue == NULL) {
3128 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3129 return NT_STATUS_OK;
3132 while (xconn->smb2.send_queue != NULL) {
3133 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3135 if (e->sendfile_header != NULL) {
3136 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3137 size_t size = 0;
3138 size_t i = 0;
3139 uint8_t *buf;
3141 for (i=0; i < e->count; i++) {
3142 size += e->vector[i].iov_len;
3145 if (size <= e->sendfile_header->length) {
3146 buf = e->sendfile_header->data;
3147 } else {
3148 buf = talloc_array(e->mem_ctx, uint8_t, size);
3149 if (buf == NULL) {
3150 return NT_STATUS_NO_MEMORY;
3154 size = 0;
3155 for (i=0; i < e->count; i++) {
3156 memcpy(buf+size,
3157 e->vector[i].iov_base,
3158 e->vector[i].iov_len);
3159 size += e->vector[i].iov_len;
3162 e->sendfile_header->data = buf;
3163 e->sendfile_header->length = size;
3164 e->sendfile_status = &status;
3165 e->count = 0;
3167 xconn->smb2.send_queue_len--;
3168 DLIST_REMOVE(xconn->smb2.send_queue, e);
3170 * This triggers the sendfile path via
3171 * the destructor.
3173 talloc_free(e->mem_ctx);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 return status;
3178 continue;
3181 ret = writev(xconn->transport.sock, e->vector, e->count);
3182 if (ret == 0) {
3183 /* propagate end of file */
3184 return NT_STATUS_INTERNAL_ERROR;
3186 err = socket_error_from_errno(ret, errno, &retry);
3187 if (retry) {
3188 /* retry later */
3189 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3190 return NT_STATUS_OK;
3192 if (err != 0) {
3193 return map_nt_error_from_unix_common(err);
3195 while (ret > 0) {
3196 if (ret < e->vector[0].iov_len) {
3197 uint8_t *base;
3198 base = (uint8_t *)e->vector[0].iov_base;
3199 base += ret;
3200 e->vector[0].iov_base = (void *)base;
3201 e->vector[0].iov_len -= ret;
3202 break;
3204 ret -= e->vector[0].iov_len;
3205 e->vector += 1;
3206 e->count -= 1;
3210 * there're maybe some empty vectors at the end
3211 * which we need to skip, otherwise we would get
3212 * ret == 0 from the readv() call and return EPIPE
3214 while (e->count > 0) {
3215 if (e->vector[0].iov_len > 0) {
3216 break;
3218 e->vector += 1;
3219 e->count -= 1;
3222 if (e->count > 0) {
3223 /* we have more to write */
3224 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3225 return NT_STATUS_OK;
3228 xconn->smb2.send_queue_len--;
3229 DLIST_REMOVE(xconn->smb2.send_queue, e);
3230 talloc_free(e->mem_ctx);
3233 return NT_STATUS_OK;
3236 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3237 uint16_t fde_flags)
3239 struct smbd_server_connection *sconn = xconn->client->sconn;
3240 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3241 struct smbd_smb2_request *req = NULL;
3242 size_t min_recvfile_size = UINT32_MAX;
3243 int ret;
3244 int err;
3245 bool retry;
3246 NTSTATUS status;
3247 NTTIME now;
3249 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3251 * we're not supposed to do any io
3253 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3254 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3255 return NT_STATUS_OK;
3258 if (fde_flags & TEVENT_FD_WRITE) {
3259 status = smbd_smb2_flush_send_queue(xconn);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 return status;
3265 if (!(fde_flags & TEVENT_FD_READ)) {
3266 return NT_STATUS_OK;
3269 if (state->req == NULL) {
3270 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3271 return NT_STATUS_OK;
3274 again:
3275 if (!state->hdr.done) {
3276 state->hdr.done = true;
3278 state->vector.iov_base = (void *)state->hdr.nbt;
3279 state->vector.iov_len = NBT_HDR_SIZE;
3282 ret = readv(xconn->transport.sock, &state->vector, 1);
3283 if (ret == 0) {
3284 /* propagate end of file */
3285 return NT_STATUS_END_OF_FILE;
3287 err = socket_error_from_errno(ret, errno, &retry);
3288 if (retry) {
3289 /* retry later */
3290 TEVENT_FD_READABLE(xconn->transport.fde);
3291 return NT_STATUS_OK;
3293 if (err != 0) {
3294 return map_nt_error_from_unix_common(err);
3297 if (ret < state->vector.iov_len) {
3298 uint8_t *base;
3299 base = (uint8_t *)state->vector.iov_base;
3300 base += ret;
3301 state->vector.iov_base = (void *)base;
3302 state->vector.iov_len -= ret;
3303 /* we have more to read */
3304 TEVENT_FD_READABLE(xconn->transport.fde);
3305 return NT_STATUS_OK;
3308 if (state->pktlen > 0) {
3309 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3311 * Not a possible receivefile write.
3312 * Read the rest of the data.
3314 state->doing_receivefile = false;
3316 state->pktbuf = talloc_realloc(state->req,
3317 state->pktbuf,
3318 uint8_t,
3319 state->pktfull);
3320 if (state->pktbuf == NULL) {
3321 return NT_STATUS_NO_MEMORY;
3324 state->vector.iov_base = (void *)(state->pktbuf +
3325 state->pktlen);
3326 state->vector.iov_len = (state->pktfull -
3327 state->pktlen);
3329 state->pktlen = state->pktfull;
3330 goto again;
3334 * Either this is a receivefile write so we've
3335 * done a short read, or if not we have all the data.
3337 goto got_full;
3341 * Now we analyze the NBT header
3343 if (state->hdr.nbt[0] != 0x00) {
3344 state->min_recv_size = 0;
3346 state->pktfull = smb2_len(state->hdr.nbt);
3347 if (state->pktfull == 0) {
3348 goto got_full;
3351 if (state->min_recv_size != 0) {
3352 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3353 min_recvfile_size += state->min_recv_size;
3356 if (state->pktfull > min_recvfile_size) {
3358 * Might be a receivefile write. Read the SMB2 HEADER +
3359 * SMB2_WRITE header first. Set 'doing_receivefile'
3360 * as we're *attempting* receivefile write. If this
3361 * turns out not to be a SMB2_WRITE request or otherwise
3362 * not suitable then we'll just read the rest of the data
3363 * the next time this function is called.
3365 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3366 state->doing_receivefile = true;
3367 } else {
3368 state->pktlen = state->pktfull;
3371 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3372 if (state->pktbuf == NULL) {
3373 return NT_STATUS_NO_MEMORY;
3376 state->vector.iov_base = (void *)state->pktbuf;
3377 state->vector.iov_len = state->pktlen;
3379 goto again;
3381 got_full:
3383 if (state->hdr.nbt[0] != 0x00) {
3384 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3385 state->hdr.nbt[0]));
3387 req = state->req;
3388 ZERO_STRUCTP(state);
3389 state->req = req;
3390 state->min_recv_size = lp_min_receive_file_size();
3391 req = NULL;
3392 goto again;
3395 req = state->req;
3396 state->req = NULL;
3398 req->request_time = timeval_current();
3399 now = timeval_to_nttime(&req->request_time);
3401 status = smbd_smb2_inbuf_parse_compound(xconn,
3402 now,
3403 state->pktbuf,
3404 state->pktlen,
3405 req,
3406 &req->in.vector,
3407 &req->in.vector_count);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 return status;
3412 if (state->doing_receivefile) {
3413 req->smb1req = talloc_zero(req, struct smb_request);
3414 if (req->smb1req == NULL) {
3415 return NT_STATUS_NO_MEMORY;
3417 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3420 ZERO_STRUCTP(state);
3422 req->current_idx = 1;
3424 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3425 req->current_idx, req->in.vector_count));
3427 status = smbd_smb2_request_validate(req);
3428 if (!NT_STATUS_IS_OK(status)) {
3429 return status;
3432 status = smbd_smb2_request_setup_out(req);
3433 if (!NT_STATUS_IS_OK(status)) {
3434 return status;
3437 status = smbd_smb2_request_dispatch(req);
3438 if (!NT_STATUS_IS_OK(status)) {
3439 return status;
3442 sconn->num_requests++;
3444 /* The timeout_processing function isn't run nearly
3445 often enough to implement 'max log size' without
3446 overrunning the size of the file by many megabytes.
3447 This is especially true if we are running at debug
3448 level 10. Checking every 50 SMB2s is a nice
3449 tradeoff of performance vs log file size overrun. */
3451 if ((sconn->num_requests % 50) == 0 &&
3452 need_to_check_log_size()) {
3453 change_to_root_user();
3454 check_log_size();
3457 status = smbd_smb2_request_next_incoming(xconn);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 return status;
3462 return NT_STATUS_OK;
3465 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3466 struct tevent_fd *fde,
3467 uint16_t flags,
3468 void *private_data)
3470 struct smbXsrv_connection *xconn =
3471 talloc_get_type_abort(private_data,
3472 struct smbXsrv_connection);
3473 NTSTATUS status;
3475 status = smbd_smb2_io_handler(xconn, flags);
3476 if (!NT_STATUS_IS_OK(status)) {
3477 smbd_server_connection_terminate(xconn, nt_errstr(status));
3478 return;