ctdb-tests: Need to drop public IPs in kill-failover tests
[Samba.git] / source3 / smbd / smb2_server.c
blob3f23e2a797929da6ae5d01fdca518d5c03c6e509
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 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
2872 uint16_t new_epoch,
2873 uint32_t lease_flags,
2874 struct smb2_lease_key *lease_key,
2875 uint32_t current_lease_state,
2876 uint32_t new_lease_state)
2878 uint8_t body[0x2c];
2880 SSVAL(body, 0x00, sizeof(body));
2881 SSVAL(body, 0x02, new_epoch);
2882 SIVAL(body, 0x04, lease_flags);
2883 SBVAL(body, 0x08, lease_key->data[0]);
2884 SBVAL(body, 0x10, lease_key->data[1]);
2885 SIVAL(body, 0x18, current_lease_state);
2886 SIVAL(body, 0x1c, new_lease_state);
2887 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
2888 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2889 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2891 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
2894 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2896 NTSTATUS status;
2897 uint32_t flags;
2898 uint64_t file_id_persistent;
2899 uint64_t file_id_volatile;
2900 struct smbXsrv_open *op = NULL;
2901 struct files_struct *fsp = NULL;
2902 const uint8_t *body = NULL;
2905 * This is only called with a pktbuf
2906 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2907 * bytes
2910 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2911 /* Transform header. Cannot recvfile. */
2912 return false;
2914 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2915 /* Not SMB2. Normal error path will cope. */
2916 return false;
2918 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2919 /* Not SMB2. Normal error path will cope. */
2920 return false;
2922 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2923 /* Needs to be a WRITE. */
2924 return false;
2926 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2927 /* Chained. Cannot recvfile. */
2928 return false;
2930 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2931 if (flags & SMB2_HDR_FLAG_CHAINED) {
2932 /* Chained. Cannot recvfile. */
2933 return false;
2935 if (flags & SMB2_HDR_FLAG_SIGNED) {
2936 /* Signed. Cannot recvfile. */
2937 return false;
2940 body = &state->pktbuf[SMB2_HDR_BODY];
2942 file_id_persistent = BVAL(body, 0x10);
2943 file_id_volatile = BVAL(body, 0x18);
2945 status = smb2srv_open_lookup(state->req->xconn,
2946 file_id_persistent,
2947 file_id_volatile,
2948 0, /* now */
2949 &op);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 return false;
2954 fsp = op->compat;
2955 if (fsp == NULL) {
2956 return false;
2958 if (fsp->conn == NULL) {
2959 return false;
2962 if (IS_IPC(fsp->conn)) {
2963 return false;
2965 if (IS_PRINT(fsp->conn)) {
2966 return false;
2969 DEBUG(10,("Doing recvfile write len = %u\n",
2970 (unsigned int)(state->pktfull - state->pktlen)));
2972 return true;
2975 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
2977 struct smbd_server_connection *sconn = xconn->client->sconn;
2978 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2979 size_t max_send_queue_len;
2980 size_t cur_send_queue_len;
2982 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2984 * we're not supposed to do any io
2986 return NT_STATUS_OK;
2989 if (state->req != NULL) {
2991 * if there is already a tstream_readv_pdu
2992 * pending, we are done.
2994 return NT_STATUS_OK;
2997 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2998 cur_send_queue_len = xconn->smb2.send_queue_len;
3000 if (cur_send_queue_len > max_send_queue_len) {
3002 * if we have a lot of requests to send,
3003 * we wait until they are on the wire until we
3004 * ask for the next request.
3006 return NT_STATUS_OK;
3009 /* ask for the next request */
3010 ZERO_STRUCTP(state);
3011 state->req = smbd_smb2_request_allocate(xconn);
3012 if (state->req == NULL) {
3013 return NT_STATUS_NO_MEMORY;
3015 state->req->sconn = sconn;
3016 state->req->xconn = xconn;
3017 state->min_recv_size = lp_min_receive_file_size();
3019 TEVENT_FD_READABLE(xconn->transport.fde);
3021 return NT_STATUS_OK;
3024 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3025 const uint8_t *inpdu, size_t size)
3027 struct smbd_server_connection *sconn = xconn->client->sconn;
3028 NTSTATUS status;
3029 struct smbd_smb2_request *req = NULL;
3031 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3032 (unsigned int)size));
3034 status = smbd_initialize_smb2(xconn);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 smbd_server_connection_terminate(xconn, nt_errstr(status));
3037 return;
3040 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 smbd_server_connection_terminate(xconn, nt_errstr(status));
3043 return;
3046 status = smbd_smb2_request_validate(req);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 smbd_server_connection_terminate(xconn, nt_errstr(status));
3049 return;
3052 status = smbd_smb2_request_setup_out(req);
3053 if (!NT_STATUS_IS_OK(status)) {
3054 smbd_server_connection_terminate(xconn, nt_errstr(status));
3055 return;
3058 #ifdef WITH_PROFILE
3060 * this was already counted at the SMB1 layer =>
3061 * smbd_smb2_request_dispatch() should not count it twice.
3063 if (profile_p->request_stats.count > 0) {
3064 profile_p->request_stats.count--;
3066 #endif
3067 status = smbd_smb2_request_dispatch(req);
3068 if (!NT_STATUS_IS_OK(status)) {
3069 smbd_server_connection_terminate(xconn, nt_errstr(status));
3070 return;
3073 status = smbd_smb2_request_next_incoming(xconn);
3074 if (!NT_STATUS_IS_OK(status)) {
3075 smbd_server_connection_terminate(xconn, nt_errstr(status));
3076 return;
3079 sconn->num_requests++;
3082 static int socket_error_from_errno(int ret,
3083 int sys_errno,
3084 bool *retry)
3086 *retry = false;
3088 if (ret >= 0) {
3089 return 0;
3092 if (ret != -1) {
3093 return EIO;
3096 if (sys_errno == 0) {
3097 return EIO;
3100 if (sys_errno == EINTR) {
3101 *retry = true;
3102 return sys_errno;
3105 if (sys_errno == EINPROGRESS) {
3106 *retry = true;
3107 return sys_errno;
3110 if (sys_errno == EAGAIN) {
3111 *retry = true;
3112 return sys_errno;
3115 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3116 if (sys_errno == ENOMEM) {
3117 *retry = true;
3118 return sys_errno;
3121 #ifdef EWOULDBLOCK
3122 #if EWOULDBLOCK != EAGAIN
3123 if (sys_errno == EWOULDBLOCK) {
3124 *retry = true;
3125 return sys_errno;
3127 #endif
3128 #endif
3130 return sys_errno;
3133 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3135 int ret;
3136 int err;
3137 bool retry;
3139 if (xconn->smb2.send_queue == NULL) {
3140 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3141 return NT_STATUS_OK;
3144 while (xconn->smb2.send_queue != NULL) {
3145 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3147 if (e->sendfile_header != NULL) {
3148 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3149 size_t size = 0;
3150 size_t i = 0;
3151 uint8_t *buf;
3153 for (i=0; i < e->count; i++) {
3154 size += e->vector[i].iov_len;
3157 if (size <= e->sendfile_header->length) {
3158 buf = e->sendfile_header->data;
3159 } else {
3160 buf = talloc_array(e->mem_ctx, uint8_t, size);
3161 if (buf == NULL) {
3162 return NT_STATUS_NO_MEMORY;
3166 size = 0;
3167 for (i=0; i < e->count; i++) {
3168 memcpy(buf+size,
3169 e->vector[i].iov_base,
3170 e->vector[i].iov_len);
3171 size += e->vector[i].iov_len;
3174 e->sendfile_header->data = buf;
3175 e->sendfile_header->length = size;
3176 e->sendfile_status = &status;
3177 e->count = 0;
3179 xconn->smb2.send_queue_len--;
3180 DLIST_REMOVE(xconn->smb2.send_queue, e);
3182 * This triggers the sendfile path via
3183 * the destructor.
3185 talloc_free(e->mem_ctx);
3187 if (!NT_STATUS_IS_OK(status)) {
3188 return status;
3190 continue;
3193 ret = writev(xconn->transport.sock, e->vector, e->count);
3194 if (ret == 0) {
3195 /* propagate end of file */
3196 return NT_STATUS_INTERNAL_ERROR;
3198 err = socket_error_from_errno(ret, errno, &retry);
3199 if (retry) {
3200 /* retry later */
3201 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3202 return NT_STATUS_OK;
3204 if (err != 0) {
3205 return map_nt_error_from_unix_common(err);
3207 while (ret > 0) {
3208 if (ret < e->vector[0].iov_len) {
3209 uint8_t *base;
3210 base = (uint8_t *)e->vector[0].iov_base;
3211 base += ret;
3212 e->vector[0].iov_base = (void *)base;
3213 e->vector[0].iov_len -= ret;
3214 break;
3216 ret -= e->vector[0].iov_len;
3217 e->vector += 1;
3218 e->count -= 1;
3222 * there're maybe some empty vectors at the end
3223 * which we need to skip, otherwise we would get
3224 * ret == 0 from the readv() call and return EPIPE
3226 while (e->count > 0) {
3227 if (e->vector[0].iov_len > 0) {
3228 break;
3230 e->vector += 1;
3231 e->count -= 1;
3234 if (e->count > 0) {
3235 /* we have more to write */
3236 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3237 return NT_STATUS_OK;
3240 xconn->smb2.send_queue_len--;
3241 DLIST_REMOVE(xconn->smb2.send_queue, e);
3242 talloc_free(e->mem_ctx);
3245 return NT_STATUS_OK;
3248 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3249 uint16_t fde_flags)
3251 struct smbd_server_connection *sconn = xconn->client->sconn;
3252 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3253 struct smbd_smb2_request *req = NULL;
3254 size_t min_recvfile_size = UINT32_MAX;
3255 int ret;
3256 int err;
3257 bool retry;
3258 NTSTATUS status;
3259 NTTIME now;
3261 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3263 * we're not supposed to do any io
3265 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3266 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3267 return NT_STATUS_OK;
3270 if (fde_flags & TEVENT_FD_WRITE) {
3271 status = smbd_smb2_flush_send_queue(xconn);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 return status;
3277 if (!(fde_flags & TEVENT_FD_READ)) {
3278 return NT_STATUS_OK;
3281 if (state->req == NULL) {
3282 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3283 return NT_STATUS_OK;
3286 again:
3287 if (!state->hdr.done) {
3288 state->hdr.done = true;
3290 state->vector.iov_base = (void *)state->hdr.nbt;
3291 state->vector.iov_len = NBT_HDR_SIZE;
3294 ret = readv(xconn->transport.sock, &state->vector, 1);
3295 if (ret == 0) {
3296 /* propagate end of file */
3297 return NT_STATUS_END_OF_FILE;
3299 err = socket_error_from_errno(ret, errno, &retry);
3300 if (retry) {
3301 /* retry later */
3302 TEVENT_FD_READABLE(xconn->transport.fde);
3303 return NT_STATUS_OK;
3305 if (err != 0) {
3306 return map_nt_error_from_unix_common(err);
3309 if (ret < state->vector.iov_len) {
3310 uint8_t *base;
3311 base = (uint8_t *)state->vector.iov_base;
3312 base += ret;
3313 state->vector.iov_base = (void *)base;
3314 state->vector.iov_len -= ret;
3315 /* we have more to read */
3316 TEVENT_FD_READABLE(xconn->transport.fde);
3317 return NT_STATUS_OK;
3320 if (state->pktlen > 0) {
3321 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3323 * Not a possible receivefile write.
3324 * Read the rest of the data.
3326 state->doing_receivefile = false;
3328 state->pktbuf = talloc_realloc(state->req,
3329 state->pktbuf,
3330 uint8_t,
3331 state->pktfull);
3332 if (state->pktbuf == NULL) {
3333 return NT_STATUS_NO_MEMORY;
3336 state->vector.iov_base = (void *)(state->pktbuf +
3337 state->pktlen);
3338 state->vector.iov_len = (state->pktfull -
3339 state->pktlen);
3341 state->pktlen = state->pktfull;
3342 goto again;
3346 * Either this is a receivefile write so we've
3347 * done a short read, or if not we have all the data.
3349 goto got_full;
3353 * Now we analyze the NBT header
3355 if (state->hdr.nbt[0] != 0x00) {
3356 state->min_recv_size = 0;
3358 state->pktfull = smb2_len(state->hdr.nbt);
3359 if (state->pktfull == 0) {
3360 goto got_full;
3363 if (state->min_recv_size != 0) {
3364 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3365 min_recvfile_size += state->min_recv_size;
3368 if (state->pktfull > min_recvfile_size) {
3370 * Might be a receivefile write. Read the SMB2 HEADER +
3371 * SMB2_WRITE header first. Set 'doing_receivefile'
3372 * as we're *attempting* receivefile write. If this
3373 * turns out not to be a SMB2_WRITE request or otherwise
3374 * not suitable then we'll just read the rest of the data
3375 * the next time this function is called.
3377 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3378 state->doing_receivefile = true;
3379 } else {
3380 state->pktlen = state->pktfull;
3383 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3384 if (state->pktbuf == NULL) {
3385 return NT_STATUS_NO_MEMORY;
3388 state->vector.iov_base = (void *)state->pktbuf;
3389 state->vector.iov_len = state->pktlen;
3391 goto again;
3393 got_full:
3395 if (state->hdr.nbt[0] != 0x00) {
3396 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3397 state->hdr.nbt[0]));
3399 req = state->req;
3400 ZERO_STRUCTP(state);
3401 state->req = req;
3402 state->min_recv_size = lp_min_receive_file_size();
3403 req = NULL;
3404 goto again;
3407 req = state->req;
3408 state->req = NULL;
3410 req->request_time = timeval_current();
3411 now = timeval_to_nttime(&req->request_time);
3413 status = smbd_smb2_inbuf_parse_compound(xconn,
3414 now,
3415 state->pktbuf,
3416 state->pktlen,
3417 req,
3418 &req->in.vector,
3419 &req->in.vector_count);
3420 if (!NT_STATUS_IS_OK(status)) {
3421 return status;
3424 if (state->doing_receivefile) {
3425 req->smb1req = talloc_zero(req, struct smb_request);
3426 if (req->smb1req == NULL) {
3427 return NT_STATUS_NO_MEMORY;
3429 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3432 ZERO_STRUCTP(state);
3434 req->current_idx = 1;
3436 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3437 req->current_idx, req->in.vector_count));
3439 status = smbd_smb2_request_validate(req);
3440 if (!NT_STATUS_IS_OK(status)) {
3441 return status;
3444 status = smbd_smb2_request_setup_out(req);
3445 if (!NT_STATUS_IS_OK(status)) {
3446 return status;
3449 status = smbd_smb2_request_dispatch(req);
3450 if (!NT_STATUS_IS_OK(status)) {
3451 return status;
3454 sconn->num_requests++;
3456 /* The timeout_processing function isn't run nearly
3457 often enough to implement 'max log size' without
3458 overrunning the size of the file by many megabytes.
3459 This is especially true if we are running at debug
3460 level 10. Checking every 50 SMB2s is a nice
3461 tradeoff of performance vs log file size overrun. */
3463 if ((sconn->num_requests % 50) == 0 &&
3464 need_to_check_log_size()) {
3465 change_to_root_user();
3466 check_log_size();
3469 status = smbd_smb2_request_next_incoming(xconn);
3470 if (!NT_STATUS_IS_OK(status)) {
3471 return status;
3474 return NT_STATUS_OK;
3477 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3478 struct tevent_fd *fde,
3479 uint16_t flags,
3480 void *private_data)
3482 struct smbXsrv_connection *xconn =
3483 talloc_get_type_abort(private_data,
3484 struct smbXsrv_connection);
3485 NTSTATUS status;
3487 status = smbd_smb2_io_handler(xconn, flags);
3488 if (!NT_STATUS_IS_OK(status)) {
3489 smbd_server_connection_terminate(xconn, nt_errstr(status));
3490 return;