s3:smb2_server: allow SMB2_HDR_FLAG_PRIORITY_MASK for SMB >= 3.1.1
[Samba.git] / source3 / smbd / smb2_server.c
blob9658534a06240044c0fe0bdbac56bcb718b311a2
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 "lib/util/iov_buf.h"
32 #include "auth.h"
34 static void smbd_smb2_connection_handler(struct tevent_context *ev,
35 struct tevent_fd *fde,
36 uint16_t flags,
37 void *private_data);
38 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
40 static const struct smbd_smb2_dispatch_table {
41 uint16_t opcode;
42 const char *name;
43 bool need_session;
44 bool need_tcon;
45 bool as_root;
46 uint16_t fileid_ofs;
47 bool allow_invalid_fileid;
48 } smbd_smb2_table[] = {
49 #define _OP(o) .opcode = o, .name = #o
51 _OP(SMB2_OP_NEGPROT),
52 .as_root = true,
53 },{
54 _OP(SMB2_OP_SESSSETUP),
55 .as_root = true,
56 },{
57 _OP(SMB2_OP_LOGOFF),
58 .need_session = true,
59 .as_root = true,
60 },{
61 _OP(SMB2_OP_TCON),
62 .need_session = true,
64 * This call needs to be run as root.
66 * smbd_smb2_request_process_tcon()
67 * calls make_connection_snum(), which will call
68 * change_to_user(), when needed.
70 .as_root = true,
71 },{
72 _OP(SMB2_OP_TDIS),
73 .need_session = true,
74 .need_tcon = true,
75 .as_root = true,
76 },{
77 _OP(SMB2_OP_CREATE),
78 .need_session = true,
79 .need_tcon = true,
80 },{
81 _OP(SMB2_OP_CLOSE),
82 .need_session = true,
83 .need_tcon = true,
84 .fileid_ofs = 0x08,
85 },{
86 _OP(SMB2_OP_FLUSH),
87 .need_session = true,
88 .need_tcon = true,
89 .fileid_ofs = 0x08,
90 },{
91 _OP(SMB2_OP_READ),
92 .need_session = true,
93 .need_tcon = true,
94 .fileid_ofs = 0x10,
95 },{
96 _OP(SMB2_OP_WRITE),
97 .need_session = true,
98 .need_tcon = true,
99 .fileid_ofs = 0x10,
101 _OP(SMB2_OP_LOCK),
102 .need_session = true,
103 .need_tcon = true,
104 .fileid_ofs = 0x08,
106 _OP(SMB2_OP_IOCTL),
107 .need_session = true,
108 .need_tcon = true,
109 .fileid_ofs = 0x08,
110 .allow_invalid_fileid = true,
112 _OP(SMB2_OP_CANCEL),
113 .as_root = true,
115 _OP(SMB2_OP_KEEPALIVE),
116 .as_root = true,
118 _OP(SMB2_OP_QUERY_DIRECTORY),
119 .need_session = true,
120 .need_tcon = true,
121 .fileid_ofs = 0x08,
123 _OP(SMB2_OP_NOTIFY),
124 .need_session = true,
125 .need_tcon = true,
126 .fileid_ofs = 0x08,
128 _OP(SMB2_OP_GETINFO),
129 .need_session = true,
130 .need_tcon = true,
131 .fileid_ofs = 0x18,
133 _OP(SMB2_OP_SETINFO),
134 .need_session = true,
135 .need_tcon = true,
136 .fileid_ofs = 0x10,
138 _OP(SMB2_OP_BREAK),
139 .need_session = true,
140 .need_tcon = true,
142 * we do not set
143 * .fileid_ofs here
144 * as LEASE breaks does not
145 * have a file id
150 const char *smb2_opcode_name(uint16_t opcode)
152 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
153 return "Bad SMB2 opcode";
155 return smbd_smb2_table[opcode].name;
158 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
160 const struct smbd_smb2_dispatch_table *ret = NULL;
162 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
163 return NULL;
166 ret = &smbd_smb2_table[opcode];
168 SMB_ASSERT(ret->opcode == opcode);
170 return ret;
173 static void print_req_vectors(const struct smbd_smb2_request *req)
175 int i;
177 for (i = 0; i < req->in.vector_count; i++) {
178 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
179 (unsigned int)i,
180 (unsigned int)req->in.vector[i].iov_len);
182 for (i = 0; i < req->out.vector_count; i++) {
183 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
184 (unsigned int)i,
185 (unsigned int)req->out.vector[i].iov_len);
189 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
191 if (size < (4 + SMB2_HDR_BODY)) {
192 return false;
195 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
196 return false;
199 return true;
202 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
204 TALLOC_FREE(xconn->transport.fde);
206 xconn->smb2.credits.seq_low = 0;
207 xconn->smb2.credits.seq_range = 1;
208 xconn->smb2.credits.granted = 1;
209 xconn->smb2.credits.max = lp_smb2_max_credits();
210 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
211 xconn->smb2.credits.max);
212 if (xconn->smb2.credits.bitmap == NULL) {
213 return NT_STATUS_NO_MEMORY;
216 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
217 xconn,
218 xconn->transport.sock,
219 TEVENT_FD_READ,
220 smbd_smb2_connection_handler,
221 xconn);
222 if (xconn->transport.fde == NULL) {
223 return NT_STATUS_NO_MEMORY;
226 /* Ensure child is set to non-blocking mode */
227 set_blocking(xconn->transport.sock, false);
228 return NT_STATUS_OK;
231 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
232 #define _smb2_setlen(_buf,len) do { \
233 uint8_t *buf = (uint8_t *)_buf; \
234 buf[0] = 0; \
235 buf[1] = ((len)&0xFF0000)>>16; \
236 buf[2] = ((len)&0xFF00)>>8; \
237 buf[3] = (len)&0xFF; \
238 } while (0)
240 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
242 ssize_t len;
244 if (count == 0) {
245 return false;
248 len = iov_buflen(vector+1, count-1);
250 if ((len == -1) || (len > 0xFFFFFF)) {
251 return false;
254 _smb2_setlen(vector[0].iov_base, len);
255 return true;
258 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
260 if (req->first_key.length > 0) {
261 data_blob_clear_free(&req->first_key);
263 if (req->last_key.length > 0) {
264 data_blob_clear_free(&req->last_key);
266 return 0;
269 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
271 TALLOC_CTX *mem_pool;
272 struct smbd_smb2_request *req;
274 #if 0
275 /* Enable this to find subtle valgrind errors. */
276 mem_pool = talloc_init("smbd_smb2_request_allocate");
277 #else
278 mem_pool = talloc_tos();
279 #endif
280 if (mem_pool == NULL) {
281 return NULL;
284 req = talloc_zero(mem_pool, struct smbd_smb2_request);
285 if (req == NULL) {
286 talloc_free(mem_pool);
287 return NULL;
289 talloc_reparent(mem_pool, mem_ctx, req);
290 #if 0
291 TALLOC_FREE(mem_pool);
292 #endif
294 req->last_session_id = UINT64_MAX;
295 req->last_tid = UINT32_MAX;
297 talloc_set_destructor(req, smbd_smb2_request_destructor);
299 return req;
302 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
303 NTTIME now,
304 uint8_t *buf,
305 size_t buflen,
306 struct smbd_smb2_request *req,
307 struct iovec **piov,
308 int *pnum_iov)
310 TALLOC_CTX *mem_ctx = req;
311 struct iovec *iov;
312 int num_iov = 1;
313 size_t taken = 0;
314 uint8_t *first_hdr = buf;
315 size_t verified_buflen = 0;
316 uint8_t *tf = NULL;
317 size_t tf_len = 0;
320 * Note: index '0' is reserved for the transport protocol
322 iov = req->in._vector;
324 while (taken < buflen) {
325 size_t len = buflen - taken;
326 uint8_t *hdr = first_hdr + taken;
327 struct iovec *cur;
328 size_t full_size;
329 size_t next_command_ofs;
330 uint16_t body_size;
331 uint8_t *body = NULL;
332 uint32_t dyn_size;
333 uint8_t *dyn = NULL;
334 struct iovec *iov_alloc = NULL;
336 if (iov != req->in._vector) {
337 iov_alloc = iov;
340 if (verified_buflen > taken) {
341 len = verified_buflen - taken;
342 } else {
343 tf = NULL;
344 tf_len = 0;
347 if (len < 4) {
348 DEBUG(10, ("%d bytes left, expected at least %d\n",
349 (int)len, 4));
350 goto inval;
352 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
353 struct smbXsrv_session *s = NULL;
354 uint64_t uid;
355 struct iovec tf_iov[2];
356 NTSTATUS status;
357 size_t enc_len;
359 if (xconn->protocol < PROTOCOL_SMB2_24) {
360 DEBUG(10, ("Got SMB2_TRANSFORM header, "
361 "but dialect[0x%04X] is used\n",
362 xconn->smb2.server.dialect));
363 goto inval;
366 if (xconn->smb2.server.cipher == 0) {
367 DEBUG(10, ("Got SMB2_TRANSFORM header, "
368 "but not negotiated "
369 "client[0x%08X] server[0x%08X]\n",
370 xconn->smb2.client.capabilities,
371 xconn->smb2.server.capabilities));
372 goto inval;
375 if (len < SMB2_TF_HDR_SIZE) {
376 DEBUG(1, ("%d bytes left, expected at least %d\n",
377 (int)len, SMB2_TF_HDR_SIZE));
378 goto inval;
380 tf = hdr;
381 tf_len = SMB2_TF_HDR_SIZE;
382 taken += tf_len;
384 hdr = first_hdr + taken;
385 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
386 uid = BVAL(tf, SMB2_TF_SESSION_ID);
388 if (len < SMB2_TF_HDR_SIZE + enc_len) {
389 DEBUG(1, ("%d bytes left, expected at least %d\n",
390 (int)len,
391 (int)(SMB2_TF_HDR_SIZE + enc_len)));
392 goto inval;
395 status = smb2srv_session_lookup(xconn, uid, now, &s);
396 if (s == NULL) {
397 DEBUG(1, ("invalid session[%llu] in "
398 "SMB2_TRANSFORM header\n",
399 (unsigned long long)uid));
400 TALLOC_FREE(iov_alloc);
401 return NT_STATUS_USER_SESSION_DELETED;
404 tf_iov[0].iov_base = (void *)tf;
405 tf_iov[0].iov_len = tf_len;
406 tf_iov[1].iov_base = (void *)hdr;
407 tf_iov[1].iov_len = enc_len;
409 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
410 xconn->smb2.server.cipher,
411 tf_iov, 2);
412 if (!NT_STATUS_IS_OK(status)) {
413 TALLOC_FREE(iov_alloc);
414 return status;
417 verified_buflen = taken + enc_len;
418 len = enc_len;
422 * We need the header plus the body length field
425 if (len < SMB2_HDR_BODY + 2) {
426 DEBUG(10, ("%d bytes left, expected at least %d\n",
427 (int)len, SMB2_HDR_BODY));
428 goto inval;
430 if (IVAL(hdr, 0) != SMB2_MAGIC) {
431 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
432 IVAL(hdr, 0)));
433 goto inval;
435 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
436 DEBUG(10, ("Got HDR len %d, expected %d\n",
437 SVAL(hdr, 4), SMB2_HDR_BODY));
438 goto inval;
441 full_size = len;
442 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
443 body_size = SVAL(hdr, SMB2_HDR_BODY);
445 if (next_command_ofs != 0) {
446 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
447 goto inval;
449 if (next_command_ofs > full_size) {
450 goto inval;
452 full_size = next_command_ofs;
454 if (body_size < 2) {
455 goto inval;
457 body_size &= 0xfffe;
459 if (body_size > (full_size - SMB2_HDR_BODY)) {
461 * let the caller handle the error
463 body_size = full_size - SMB2_HDR_BODY;
465 body = hdr + SMB2_HDR_BODY;
466 dyn = body + body_size;
467 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
469 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
470 struct iovec *iov_tmp = NULL;
472 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
473 struct iovec,
474 num_iov +
475 SMBD_SMB2_NUM_IOV_PER_REQ);
476 if (iov_tmp == NULL) {
477 TALLOC_FREE(iov_alloc);
478 return NT_STATUS_NO_MEMORY;
481 if (iov_alloc == NULL) {
482 memcpy(iov_tmp,
483 req->in._vector,
484 sizeof(req->in._vector));
487 iov = iov_tmp;
489 cur = &iov[num_iov];
490 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
492 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
493 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
494 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
495 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
496 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
497 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
498 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
499 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
501 taken += full_size;
504 *piov = iov;
505 *pnum_iov = num_iov;
506 return NT_STATUS_OK;
508 inval:
509 if (iov != req->in._vector) {
510 TALLOC_FREE(iov);
512 return NT_STATUS_INVALID_PARAMETER;
515 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
516 const uint8_t *_inpdu, size_t size,
517 struct smbd_smb2_request **_req)
519 struct smbd_server_connection *sconn = xconn->client->sconn;
520 struct smbd_smb2_request *req;
521 uint32_t protocol_version;
522 uint8_t *inpdu = NULL;
523 const uint8_t *inhdr = NULL;
524 uint16_t cmd;
525 uint32_t next_command_ofs;
526 NTSTATUS status;
527 NTTIME now;
529 if (size < (SMB2_HDR_BODY + 2)) {
530 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
531 return NT_STATUS_INVALID_PARAMETER;
534 inhdr = _inpdu;
536 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
537 if (protocol_version != SMB2_MAGIC) {
538 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
539 protocol_version));
540 return NT_STATUS_INVALID_PARAMETER;
543 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
544 if (cmd != SMB2_OP_NEGPROT) {
545 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
546 cmd));
547 return NT_STATUS_INVALID_PARAMETER;
550 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
551 if (next_command_ofs != 0) {
552 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
553 next_command_ofs));
554 return NT_STATUS_INVALID_PARAMETER;
557 req = smbd_smb2_request_allocate(xconn);
558 if (req == NULL) {
559 return NT_STATUS_NO_MEMORY;
561 req->sconn = sconn;
562 req->xconn = xconn;
564 inpdu = talloc_memdup(req, _inpdu, size);
565 if (inpdu == NULL) {
566 return NT_STATUS_NO_MEMORY;
569 req->request_time = timeval_current();
570 now = timeval_to_nttime(&req->request_time);
572 status = smbd_smb2_inbuf_parse_compound(xconn,
573 now,
574 inpdu,
575 size,
576 req, &req->in.vector,
577 &req->in.vector_count);
578 if (!NT_STATUS_IS_OK(status)) {
579 TALLOC_FREE(req);
580 return status;
583 req->current_idx = 1;
585 *_req = req;
586 return NT_STATUS_OK;
589 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
590 uint64_t message_id, uint64_t seq_id)
592 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
593 unsigned int offset;
594 uint64_t seq_tmp;
596 seq_tmp = xconn->smb2.credits.seq_low;
597 if (seq_id < seq_tmp) {
598 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
599 "%llu (sequence id %llu) "
600 "(granted = %u, low = %llu, range = %u)\n",
601 (unsigned long long)message_id,
602 (unsigned long long)seq_id,
603 (unsigned int)xconn->smb2.credits.granted,
604 (unsigned long long)xconn->smb2.credits.seq_low,
605 (unsigned int)xconn->smb2.credits.seq_range));
606 return false;
609 seq_tmp += xconn->smb2.credits.seq_range;
610 if (seq_id >= seq_tmp) {
611 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
612 "%llu (sequence id %llu) "
613 "(granted = %u, low = %llu, range = %u)\n",
614 (unsigned long long)message_id,
615 (unsigned long long)seq_id,
616 (unsigned int)xconn->smb2.credits.granted,
617 (unsigned long long)xconn->smb2.credits.seq_low,
618 (unsigned int)xconn->smb2.credits.seq_range));
619 return false;
622 offset = seq_id % xconn->smb2.credits.max;
624 if (bitmap_query(credits_bm, offset)) {
625 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
626 "%llu (sequence id %llu) "
627 "(granted = %u, low = %llu, range = %u) "
628 "(bm offset %u)\n",
629 (unsigned long long)message_id,
630 (unsigned long long)seq_id,
631 (unsigned int)xconn->smb2.credits.granted,
632 (unsigned long long)xconn->smb2.credits.seq_low,
633 (unsigned int)xconn->smb2.credits.seq_range,
634 offset));
635 return false;
638 /* Mark the message_ids as seen in the bitmap. */
639 bitmap_set(credits_bm, offset);
641 if (seq_id != xconn->smb2.credits.seq_low) {
642 return true;
646 * Move the window forward by all the message_id's
647 * already seen.
649 while (bitmap_query(credits_bm, offset)) {
650 DEBUG(10,("smb2_validate_sequence_number: clearing "
651 "id %llu (position %u) from bitmap\n",
652 (unsigned long long)(xconn->smb2.credits.seq_low),
653 offset));
654 bitmap_clear(credits_bm, offset);
656 xconn->smb2.credits.seq_low += 1;
657 xconn->smb2.credits.seq_range -= 1;
658 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
661 return true;
664 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
665 const uint8_t *inhdr)
667 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
668 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
669 uint16_t credit_charge = 1;
670 uint64_t i;
672 if (opcode == SMB2_OP_CANCEL) {
673 /* SMB2_CANCEL requests by definition resend messageids. */
674 return true;
677 if (xconn->smb2.credits.multicredit) {
678 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
679 credit_charge = MAX(credit_charge, 1);
682 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
683 "credits_granted %llu, "
684 "seqnum low/range: %llu/%llu\n",
685 (unsigned long long) message_id,
686 (unsigned long long) credit_charge,
687 (unsigned long long) xconn->smb2.credits.granted,
688 (unsigned long long) xconn->smb2.credits.seq_low,
689 (unsigned long long) xconn->smb2.credits.seq_range));
691 if (xconn->smb2.credits.granted < credit_charge) {
692 DEBUG(0, ("smb2_validate_message_id: client used more "
693 "credits than granted, mid %llu, charge %llu, "
694 "credits_granted %llu, "
695 "seqnum low/range: %llu/%llu\n",
696 (unsigned long long) message_id,
697 (unsigned long long) credit_charge,
698 (unsigned long long) xconn->smb2.credits.granted,
699 (unsigned long long) xconn->smb2.credits.seq_low,
700 (unsigned long long) xconn->smb2.credits.seq_range));
701 return false;
705 * now check the message ids
707 * for multi-credit requests we need to check all current mid plus
708 * the implicit mids caused by the credit charge
709 * e.g. current mid = 15, charge 5 => mark 15-19 as used
712 for (i = 0; i <= (credit_charge-1); i++) {
713 uint64_t id = message_id + i;
714 bool ok;
716 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
717 (unsigned long long)message_id,
718 credit_charge,
719 (unsigned long long)id));
721 ok = smb2_validate_sequence_number(xconn, message_id, id);
722 if (!ok) {
723 return false;
727 /* substract used credits */
728 xconn->smb2.credits.granted -= credit_charge;
730 return true;
733 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
735 int count;
736 int idx;
738 count = req->in.vector_count;
740 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
741 /* It's not a SMB2 request */
742 return NT_STATUS_INVALID_PARAMETER;
745 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
746 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
747 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
748 const uint8_t *inhdr = NULL;
750 if (hdr->iov_len != SMB2_HDR_BODY) {
751 return NT_STATUS_INVALID_PARAMETER;
754 if (body->iov_len < 2) {
755 return NT_STATUS_INVALID_PARAMETER;
758 inhdr = (const uint8_t *)hdr->iov_base;
760 /* Check the SMB2 header */
761 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
762 return NT_STATUS_INVALID_PARAMETER;
765 if (!smb2_validate_message_id(req->xconn, inhdr)) {
766 return NT_STATUS_INVALID_PARAMETER;
770 return NT_STATUS_OK;
773 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
774 const struct iovec *in_vector,
775 struct iovec *out_vector)
777 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
778 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
779 uint16_t credit_charge = 1;
780 uint16_t credits_requested;
781 uint32_t out_flags;
782 uint16_t cmd;
783 NTSTATUS out_status;
784 uint16_t credits_granted = 0;
785 uint64_t credits_possible;
786 uint16_t current_max_credits;
789 * first we grant only 1/16th of the max range.
791 * Windows also starts with the 1/16th and then grants
792 * more later. I was only able to trigger higher
793 * values, when using a very high credit charge.
795 * TODO: scale up depending on load, free memory
796 * or other stuff.
797 * Maybe also on the relationship between number
798 * of requests and the used sequence number.
799 * Which means we would grant more credits
800 * for client which use multi credit requests.
802 current_max_credits = xconn->smb2.credits.max / 16;
803 current_max_credits = MAX(current_max_credits, 1);
805 if (xconn->smb2.credits.multicredit) {
806 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
807 credit_charge = MAX(credit_charge, 1);
810 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
811 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
812 credits_requested = MAX(credits_requested, 1);
813 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
814 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
816 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
818 if (xconn->smb2.credits.max < credit_charge) {
819 smbd_server_connection_terminate(xconn,
820 "client error: credit charge > max credits\n");
821 return;
824 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
826 * In case we already send an async interim
827 * response, we should not grant
828 * credits on the final response.
830 credits_granted = 0;
831 } else {
832 uint16_t additional_possible =
833 xconn->smb2.credits.max - credit_charge;
834 uint16_t additional_max = 0;
835 uint16_t additional_credits = credits_requested - 1;
837 switch (cmd) {
838 case SMB2_OP_NEGPROT:
839 break;
840 case SMB2_OP_SESSSETUP:
842 * Windows 2012 RC1 starts to grant
843 * additional credits
844 * with a successful session setup
846 if (NT_STATUS_IS_OK(out_status)) {
847 additional_max = 32;
849 break;
850 default:
852 * We match windows and only grant additional credits
853 * in chunks of 32.
855 additional_max = 32;
856 break;
859 additional_max = MIN(additional_max, additional_possible);
860 additional_credits = MIN(additional_credits, additional_max);
862 credits_granted = credit_charge + additional_credits;
866 * sequence numbers should not wrap
868 * 1. calculate the possible credits until
869 * the sequence numbers start to wrap on 64-bit.
871 * 2. UINT64_MAX is used for Break Notifications.
873 * 2. truncate the possible credits to the maximum
874 * credits we want to grant to the client in total.
876 * 3. remove the range we'll already granted to the client
877 * this makes sure the client consumes the lowest sequence
878 * number, before we can grant additional credits.
880 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
881 if (credits_possible > 0) {
882 /* remove UINT64_MAX */
883 credits_possible -= 1;
885 credits_possible = MIN(credits_possible, current_max_credits);
886 credits_possible -= xconn->smb2.credits.seq_range;
888 credits_granted = MIN(credits_granted, credits_possible);
890 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
891 xconn->smb2.credits.granted += credits_granted;
892 xconn->smb2.credits.seq_range += credits_granted;
894 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
895 "granted %u, current possible/max %u/%u, "
896 "total granted/max/low/range %u/%u/%llu/%u\n",
897 (unsigned int)credits_requested,
898 (unsigned int)credit_charge,
899 (unsigned int)credits_granted,
900 (unsigned int)credits_possible,
901 (unsigned int)current_max_credits,
902 (unsigned int)xconn->smb2.credits.granted,
903 (unsigned int)xconn->smb2.credits.max,
904 (unsigned long long)xconn->smb2.credits.seq_low,
905 (unsigned int)xconn->smb2.credits.seq_range));
908 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
909 struct smbd_smb2_request *outreq)
911 int count, idx;
912 uint16_t total_credits = 0;
914 count = outreq->out.vector_count;
916 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
917 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
918 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
919 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
921 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
923 /* To match Windows, count up what we
924 just granted. */
925 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
926 /* Set to zero in all but the last reply. */
927 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
928 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
929 } else {
930 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
935 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
937 if (req->current_idx <= 1) {
938 if (size <= sizeof(req->out._body)) {
939 return data_blob_const(req->out._body, size);
943 return data_blob_talloc(req, NULL, size);
946 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
948 struct smbXsrv_connection *xconn = req->xconn;
949 TALLOC_CTX *mem_ctx;
950 struct iovec *vector;
951 int count;
952 int idx;
953 bool ok;
955 count = req->in.vector_count;
956 if (count <= ARRAY_SIZE(req->out._vector)) {
957 mem_ctx = req;
958 vector = req->out._vector;
959 } else {
960 vector = talloc_zero_array(req, struct iovec, count);
961 if (vector == NULL) {
962 return NT_STATUS_NO_MEMORY;
964 mem_ctx = vector;
967 vector[0].iov_base = req->out.nbt_hdr;
968 vector[0].iov_len = 4;
969 SIVAL(req->out.nbt_hdr, 0, 0);
971 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
972 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
973 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
974 uint8_t *outhdr = NULL;
975 uint8_t *outbody = NULL;
976 uint32_t next_command_ofs = 0;
977 struct iovec *current = &vector[idx];
979 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
980 /* we have a next command -
981 * setup for the error case. */
982 next_command_ofs = SMB2_HDR_BODY + 9;
985 if (idx == 1) {
986 outhdr = req->out._hdr;
987 } else {
988 outhdr = talloc_zero_array(mem_ctx, uint8_t,
989 OUTVEC_ALLOC_SIZE);
990 if (outhdr == NULL) {
991 return NT_STATUS_NO_MEMORY;
995 outbody = outhdr + SMB2_HDR_BODY;
998 * SMBD_SMB2_TF_IOV_OFS might be used later
1000 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1001 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1003 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1004 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1006 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1007 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1009 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1010 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1012 /* setup the SMB2 header */
1013 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1014 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1015 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1016 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1017 SIVAL(outhdr, SMB2_HDR_STATUS,
1018 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1019 SSVAL(outhdr, SMB2_HDR_OPCODE,
1020 SVAL(inhdr, SMB2_HDR_OPCODE));
1021 SIVAL(outhdr, SMB2_HDR_FLAGS,
1022 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1023 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1024 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1025 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1026 SIVAL(outhdr, SMB2_HDR_PID,
1027 IVAL(inhdr, SMB2_HDR_PID));
1028 SIVAL(outhdr, SMB2_HDR_TID,
1029 IVAL(inhdr, SMB2_HDR_TID));
1030 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1031 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1032 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1033 inhdr + SMB2_HDR_SIGNATURE, 16);
1035 /* setup error body header */
1036 SSVAL(outbody, 0x00, 0x08 + 1);
1037 SSVAL(outbody, 0x02, 0);
1038 SIVAL(outbody, 0x04, 0);
1041 req->out.vector = vector;
1042 req->out.vector_count = count;
1044 /* setup the length of the NBT packet */
1045 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1046 if (!ok) {
1047 return NT_STATUS_INVALID_PARAMETER_MIX;
1050 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1052 return NT_STATUS_OK;
1055 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1056 const char *reason,
1057 const char *location)
1059 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1060 reason, location));
1061 exit_server_cleanly(reason);
1064 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1065 struct iovec *outvec,
1066 const struct iovec *srcvec)
1068 const uint8_t *srctf;
1069 size_t srctf_len;
1070 const uint8_t *srchdr;
1071 size_t srchdr_len;
1072 const uint8_t *srcbody;
1073 size_t srcbody_len;
1074 const uint8_t *expected_srcbody;
1075 const uint8_t *srcdyn;
1076 size_t srcdyn_len;
1077 const uint8_t *expected_srcdyn;
1078 uint8_t *dsttf;
1079 uint8_t *dsthdr;
1080 uint8_t *dstbody;
1081 uint8_t *dstdyn;
1083 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1084 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1085 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1086 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1087 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1088 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1089 expected_srcbody = srchdr + SMB2_HDR_BODY;
1090 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1091 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1092 expected_srcdyn = srcbody + 8;
1094 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1095 return false;
1098 if (srchdr_len != SMB2_HDR_BODY) {
1099 return false;
1102 if (srctf_len == SMB2_TF_HDR_SIZE) {
1103 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1104 if (dsttf == NULL) {
1105 return false;
1107 } else {
1108 dsttf = NULL;
1110 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1111 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1113 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1114 * be allocated with size OUTVEC_ALLOC_SIZE. */
1116 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1117 if (dsthdr == NULL) {
1118 return false;
1120 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1121 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1124 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1125 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1126 * then duplicate this. Else use talloc_memdup().
1129 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1130 dstbody = dsthdr + SMB2_HDR_BODY;
1131 } else {
1132 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1133 if (dstbody == NULL) {
1134 return false;
1137 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1138 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1141 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1142 * pointing to
1143 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1144 * then duplicate this. Else use talloc_memdup().
1147 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1148 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1149 } else if (srcdyn == NULL) {
1150 dstdyn = NULL;
1151 } else {
1152 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1153 if (dstdyn == NULL) {
1154 return false;
1157 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1158 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1160 return true;
1163 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1165 struct smbd_smb2_request *newreq = NULL;
1166 struct iovec *outvec = NULL;
1167 int count = req->out.vector_count;
1168 int i;
1169 bool ok;
1171 newreq = smbd_smb2_request_allocate(req->xconn);
1172 if (!newreq) {
1173 return NULL;
1176 newreq->sconn = req->sconn;
1177 newreq->xconn = req->xconn;
1178 newreq->session = req->session;
1179 newreq->do_encryption = req->do_encryption;
1180 newreq->do_signing = req->do_signing;
1181 newreq->current_idx = req->current_idx;
1183 outvec = talloc_zero_array(newreq, struct iovec, count);
1184 if (!outvec) {
1185 TALLOC_FREE(newreq);
1186 return NULL;
1188 newreq->out.vector = outvec;
1189 newreq->out.vector_count = count;
1191 /* Setup the outvec's identically to req. */
1192 outvec[0].iov_base = newreq->out.nbt_hdr;
1193 outvec[0].iov_len = 4;
1194 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1196 /* Setup the vectors identically to the ones in req. */
1197 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1198 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1199 break;
1203 if (i < count) {
1204 /* Alloc failed. */
1205 TALLOC_FREE(newreq);
1206 return NULL;
1209 ok = smb2_setup_nbt_length(newreq->out.vector,
1210 newreq->out.vector_count);
1211 if (!ok) {
1212 TALLOC_FREE(newreq);
1213 return NULL;
1216 return newreq;
1219 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1221 struct smbXsrv_connection *xconn = req->xconn;
1222 int first_idx = 1;
1223 struct iovec *firsttf = NULL;
1224 struct iovec *outhdr_v = NULL;
1225 uint8_t *outhdr = NULL;
1226 struct smbd_smb2_request *nreq = NULL;
1227 NTSTATUS status;
1228 bool ok;
1230 /* Create a new smb2 request we'll use
1231 for the interim return. */
1232 nreq = dup_smb2_req(req);
1233 if (!nreq) {
1234 return NT_STATUS_NO_MEMORY;
1237 /* Lose the last X out vectors. They're the
1238 ones we'll be using for the async reply. */
1239 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1241 ok = smb2_setup_nbt_length(nreq->out.vector,
1242 nreq->out.vector_count);
1243 if (!ok) {
1244 return NT_STATUS_INVALID_PARAMETER_MIX;
1247 /* Step back to the previous reply. */
1248 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1249 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1250 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1251 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1252 /* And end the chain. */
1253 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1255 /* Calculate outgoing credits */
1256 smb2_calculate_credits(req, nreq);
1258 if (DEBUGLEVEL >= 10) {
1259 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1260 (unsigned int)nreq->current_idx );
1261 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1262 (unsigned int)nreq->out.vector_count );
1263 print_req_vectors(nreq);
1267 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1268 * we need to sign/encrypt here with the last/first key we remembered
1270 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1271 status = smb2_signing_encrypt_pdu(req->first_key,
1272 xconn->smb2.server.cipher,
1273 firsttf,
1274 nreq->out.vector_count - first_idx);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 return status;
1278 } else if (req->last_key.length > 0) {
1279 status = smb2_signing_sign_pdu(req->last_key,
1280 xconn->protocol,
1281 outhdr_v,
1282 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1283 if (!NT_STATUS_IS_OK(status)) {
1284 return status;
1288 nreq->queue_entry.mem_ctx = nreq;
1289 nreq->queue_entry.vector = nreq->out.vector;
1290 nreq->queue_entry.count = nreq->out.vector_count;
1291 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1292 xconn->smb2.send_queue_len++;
1294 status = smbd_smb2_flush_send_queue(xconn);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 return status;
1299 return NT_STATUS_OK;
1302 struct smbd_smb2_request_pending_state {
1303 struct smbd_smb2_send_queue queue_entry;
1304 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1305 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1308 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1309 struct tevent_timer *te,
1310 struct timeval current_time,
1311 void *private_data);
1313 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1314 struct tevent_req *subreq,
1315 uint32_t defer_time)
1317 NTSTATUS status;
1318 struct timeval defer_endtime;
1319 uint8_t *outhdr = NULL;
1320 uint32_t flags;
1322 if (!tevent_req_is_in_progress(subreq)) {
1324 * This is a performance optimization,
1325 * it avoids one tevent_loop iteration,
1326 * which means we avoid one
1327 * talloc_stackframe_pool/talloc_free pair.
1329 tevent_req_notify_callback(subreq);
1330 return NT_STATUS_OK;
1333 req->subreq = subreq;
1334 subreq = NULL;
1336 if (req->async_te) {
1337 /* We're already async. */
1338 return NT_STATUS_OK;
1341 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1342 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1343 if (flags & SMB2_HDR_FLAG_ASYNC) {
1344 /* We're already async. */
1345 return NT_STATUS_OK;
1348 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1350 * We're trying to go async in a compound request
1351 * chain. This is only allowed for opens that cause an
1352 * oplock break or for the last operation in the
1353 * chain, otherwise it is not allowed. See
1354 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1356 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1358 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1360 * Cancel the outstanding request.
1362 bool ok = tevent_req_cancel(req->subreq);
1363 if (ok) {
1364 return NT_STATUS_OK;
1366 TALLOC_FREE(req->subreq);
1367 return smbd_smb2_request_error(req,
1368 NT_STATUS_INTERNAL_ERROR);
1372 if (DEBUGLEVEL >= 10) {
1373 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1374 (unsigned int)req->current_idx );
1375 print_req_vectors(req);
1378 if (req->current_idx > 1) {
1380 * We're going async in a compound
1381 * chain after the first request has
1382 * already been processed. Send an
1383 * interim response containing the
1384 * set of replies already generated.
1386 int idx = req->current_idx;
1388 status = smb2_send_async_interim_response(req);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 return status;
1392 if (req->first_key.length > 0) {
1393 data_blob_clear_free(&req->first_key);
1396 req->current_idx = 1;
1399 * Re-arrange the in.vectors to remove what
1400 * we just sent.
1402 memmove(&req->in.vector[1],
1403 &req->in.vector[idx],
1404 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1405 req->in.vector_count = 1 + (req->in.vector_count - idx);
1407 /* Re-arrange the out.vectors to match. */
1408 memmove(&req->out.vector[1],
1409 &req->out.vector[idx],
1410 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1411 req->out.vector_count = 1 + (req->out.vector_count - idx);
1413 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1415 * We only have one remaining request as
1416 * we've processed everything else.
1417 * This is no longer a compound request.
1419 req->compound_related = false;
1420 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1421 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1422 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1425 if (req->last_key.length > 0) {
1426 data_blob_clear_free(&req->last_key);
1429 defer_endtime = timeval_current_ofs_usec(defer_time);
1430 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1431 req, defer_endtime,
1432 smbd_smb2_request_pending_timer,
1433 req);
1434 if (req->async_te == NULL) {
1435 return NT_STATUS_NO_MEMORY;
1438 return NT_STATUS_OK;
1441 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1442 struct smbXsrv_connection *xconn)
1444 struct smbXsrv_channel_global0 *c = NULL;
1445 NTSTATUS status;
1446 DATA_BLOB key = data_blob_null;
1448 status = smbXsrv_session_find_channel(session, xconn, &c);
1449 if (NT_STATUS_IS_OK(status)) {
1450 key = c->signing_key;
1453 if (key.length == 0) {
1454 key = session->global->signing_key;
1457 return key;
1460 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1461 struct tevent_timer *te,
1462 struct timeval current_time,
1463 void *private_data)
1465 struct smbd_smb2_request *req =
1466 talloc_get_type_abort(private_data,
1467 struct smbd_smb2_request);
1468 struct smbXsrv_connection *xconn = req->xconn;
1469 struct smbd_smb2_request_pending_state *state = NULL;
1470 uint8_t *outhdr = NULL;
1471 const uint8_t *inhdr = NULL;
1472 uint8_t *tf = NULL;
1473 size_t tf_len = 0;
1474 uint8_t *hdr = NULL;
1475 uint8_t *body = NULL;
1476 uint8_t *dyn = NULL;
1477 uint32_t flags = 0;
1478 uint64_t session_id = 0;
1479 uint64_t message_id = 0;
1480 uint64_t nonce_high = 0;
1481 uint64_t nonce_low = 0;
1482 uint64_t async_id = 0;
1483 NTSTATUS status;
1484 bool ok;
1486 TALLOC_FREE(req->async_te);
1488 /* Ensure our final reply matches the interim one. */
1489 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1490 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1491 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1492 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1493 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1495 async_id = message_id; /* keep it simple for now... */
1497 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1498 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1500 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1501 "going async\n",
1502 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1503 (unsigned long long)async_id ));
1506 * What we send is identical to a smbd_smb2_request_error
1507 * packet with an error status of STATUS_PENDING. Make use
1508 * of this fact sometime when refactoring. JRA.
1511 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1512 if (state == NULL) {
1513 smbd_server_connection_terminate(xconn,
1514 nt_errstr(NT_STATUS_NO_MEMORY));
1515 return;
1518 tf = state->buf + NBT_HDR_SIZE;
1519 tf_len = SMB2_TF_HDR_SIZE;
1521 hdr = tf + SMB2_TF_HDR_SIZE;
1522 body = hdr + SMB2_HDR_BODY;
1523 dyn = body + 8;
1525 if (req->do_encryption) {
1526 struct smbXsrv_session *x = req->session;
1528 nonce_high = x->nonce_high;
1529 nonce_low = x->nonce_low;
1531 x->nonce_low += 1;
1532 if (x->nonce_low == 0) {
1533 x->nonce_low += 1;
1534 x->nonce_high += 1;
1538 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1539 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1540 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1541 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1543 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1544 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1545 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1546 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1547 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1549 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1550 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1551 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1552 SBVAL(hdr, SMB2_HDR_PID, async_id);
1553 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1554 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1555 memcpy(hdr+SMB2_HDR_SIGNATURE,
1556 outhdr+SMB2_HDR_SIGNATURE, 16);
1558 SSVAL(body, 0x00, 0x08 + 1);
1560 SCVAL(body, 0x02, 0);
1561 SCVAL(body, 0x03, 0);
1562 SIVAL(body, 0x04, 0);
1563 /* Match W2K8R2... */
1564 SCVAL(dyn, 0x00, 0x21);
1566 state->vector[0].iov_base = (void *)state->buf;
1567 state->vector[0].iov_len = NBT_HDR_SIZE;
1569 if (req->do_encryption) {
1570 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1571 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1572 } else {
1573 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1574 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1577 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1578 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1580 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1581 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1583 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1584 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1586 ok = smb2_setup_nbt_length(state->vector,
1587 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1588 if (!ok) {
1589 smbd_server_connection_terminate(
1590 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1591 return;
1594 /* Ensure we correctly go through crediting. Grant
1595 the credits now, and zero credits on the final
1596 response. */
1597 smb2_set_operation_credit(req->xconn,
1598 SMBD_SMB2_IN_HDR_IOV(req),
1599 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1601 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1603 if (DEBUGLVL(10)) {
1604 int i;
1606 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1607 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1608 (unsigned int)i,
1609 (unsigned int)ARRAY_SIZE(state->vector),
1610 (unsigned int)state->vector[i].iov_len);
1614 if (req->do_encryption) {
1615 struct smbXsrv_session *x = req->session;
1616 DATA_BLOB encryption_key = x->global->encryption_key;
1618 status = smb2_signing_encrypt_pdu(encryption_key,
1619 xconn->smb2.server.cipher,
1620 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1621 SMBD_SMB2_NUM_IOV_PER_REQ);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 smbd_server_connection_terminate(xconn,
1624 nt_errstr(status));
1625 return;
1627 } else if (req->do_signing) {
1628 struct smbXsrv_session *x = req->session;
1629 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1631 status = smb2_signing_sign_pdu(signing_key,
1632 xconn->protocol,
1633 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1634 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1635 if (!NT_STATUS_IS_OK(status)) {
1636 smbd_server_connection_terminate(xconn,
1637 nt_errstr(status));
1638 return;
1642 state->queue_entry.mem_ctx = state;
1643 state->queue_entry.vector = state->vector;
1644 state->queue_entry.count = ARRAY_SIZE(state->vector);
1645 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1646 xconn->smb2.send_queue_len++;
1648 status = smbd_smb2_flush_send_queue(xconn);
1649 if (!NT_STATUS_IS_OK(status)) {
1650 smbd_server_connection_terminate(xconn,
1651 nt_errstr(status));
1652 return;
1656 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1658 struct smbXsrv_connection *xconn = req->xconn;
1659 struct smbd_smb2_request *cur;
1660 const uint8_t *inhdr;
1661 uint32_t flags;
1662 uint64_t search_message_id;
1663 uint64_t search_async_id;
1664 uint64_t found_id;
1666 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1668 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1669 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1670 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1673 * we don't need the request anymore
1674 * cancel requests never have a response
1676 DLIST_REMOVE(xconn->smb2.requests, req);
1677 TALLOC_FREE(req);
1679 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1680 const uint8_t *outhdr;
1681 uint64_t message_id;
1682 uint64_t async_id;
1684 if (cur->compound_related) {
1686 * Never cancel anything in a compound request.
1687 * Way too hard to deal with the result.
1689 continue;
1692 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1694 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1695 async_id = BVAL(outhdr, SMB2_HDR_PID);
1697 if (flags & SMB2_HDR_FLAG_ASYNC) {
1698 if (search_async_id == async_id) {
1699 found_id = async_id;
1700 break;
1702 } else {
1703 if (search_message_id == message_id) {
1704 found_id = message_id;
1705 break;
1710 if (cur && cur->subreq) {
1711 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1712 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1713 "cancel opcode[%s] mid %llu\n",
1714 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1715 (unsigned long long)found_id ));
1716 tevent_req_cancel(cur->subreq);
1719 return NT_STATUS_OK;
1722 /*************************************************************
1723 Ensure an incoming tid is a valid one for us to access.
1724 Change to the associated uid credentials and chdir to the
1725 valid tid directory.
1726 *************************************************************/
1728 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1730 const uint8_t *inhdr;
1731 uint32_t in_flags;
1732 uint32_t in_tid;
1733 struct smbXsrv_tcon *tcon;
1734 NTSTATUS status;
1735 NTTIME now = timeval_to_nttime(&req->request_time);
1737 req->tcon = NULL;
1739 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1741 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1742 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1744 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1745 in_tid = req->last_tid;
1748 req->last_tid = 0;
1750 status = smb2srv_tcon_lookup(req->session,
1751 in_tid, now, &tcon);
1752 if (!NT_STATUS_IS_OK(status)) {
1753 return status;
1756 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1757 return NT_STATUS_ACCESS_DENIED;
1760 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1761 if (!set_current_service(tcon->compat, 0, true)) {
1762 return NT_STATUS_ACCESS_DENIED;
1765 req->tcon = tcon;
1766 req->last_tid = in_tid;
1768 return NT_STATUS_OK;
1771 /*************************************************************
1772 Ensure an incoming session_id is a valid one for us to access.
1773 *************************************************************/
1775 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1777 const uint8_t *inhdr;
1778 uint32_t in_flags;
1779 uint16_t in_opcode;
1780 uint64_t in_session_id;
1781 struct smbXsrv_session *session = NULL;
1782 struct auth_session_info *session_info;
1783 NTSTATUS status;
1784 NTTIME now = timeval_to_nttime(&req->request_time);
1786 req->session = NULL;
1787 req->tcon = NULL;
1789 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1791 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1792 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1793 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1795 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1796 in_session_id = req->last_session_id;
1799 req->last_session_id = 0;
1801 /* lookup an existing session */
1802 status = smb2srv_session_lookup(req->xconn,
1803 in_session_id, now,
1804 &session);
1805 if (session) {
1806 req->session = session;
1807 req->last_session_id = in_session_id;
1809 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1810 switch (in_opcode) {
1811 case SMB2_OP_SESSSETUP:
1812 status = NT_STATUS_OK;
1813 break;
1814 default:
1815 break;
1818 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1819 switch (in_opcode) {
1820 case SMB2_OP_TCON:
1821 case SMB2_OP_CREATE:
1822 case SMB2_OP_GETINFO:
1823 case SMB2_OP_SETINFO:
1824 return NT_STATUS_INVALID_HANDLE;
1825 default:
1827 * Notice the check for
1828 * (session_info == NULL)
1829 * below.
1831 status = NT_STATUS_OK;
1832 break;
1835 if (!NT_STATUS_IS_OK(status)) {
1836 return status;
1839 session_info = session->global->auth_session_info;
1840 if (session_info == NULL) {
1841 return NT_STATUS_INVALID_HANDLE;
1844 if (in_session_id != req->xconn->client->last_session_id) {
1845 req->xconn->client->last_session_id = in_session_id;
1846 set_current_user_info(session_info->unix_info->sanitized_username,
1847 session_info->unix_info->unix_name,
1848 session_info->info->domain_name);
1851 return NT_STATUS_OK;
1854 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1855 uint32_t data_length)
1857 struct smbXsrv_connection *xconn = req->xconn;
1858 uint16_t needed_charge;
1859 uint16_t credit_charge = 1;
1860 const uint8_t *inhdr;
1862 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1864 if (xconn->smb2.credits.multicredit) {
1865 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1866 credit_charge = MAX(credit_charge, 1);
1869 needed_charge = (data_length - 1)/ 65536 + 1;
1871 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1872 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1873 credit_charge, needed_charge));
1875 if (needed_charge > credit_charge) {
1876 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1877 credit_charge, needed_charge));
1878 return NT_STATUS_INVALID_PARAMETER;
1881 return NT_STATUS_OK;
1884 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1885 size_t expected_body_size)
1887 struct iovec *inhdr_v;
1888 const uint8_t *inhdr;
1889 uint16_t opcode;
1890 const uint8_t *inbody;
1891 size_t body_size;
1892 size_t min_dyn_size = expected_body_size & 0x00000001;
1893 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1896 * The following should be checked already.
1898 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1899 return NT_STATUS_INTERNAL_ERROR;
1901 if (req->current_idx > max_idx) {
1902 return NT_STATUS_INTERNAL_ERROR;
1905 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1906 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1907 return NT_STATUS_INTERNAL_ERROR;
1909 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1910 return NT_STATUS_INTERNAL_ERROR;
1913 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1914 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1916 switch (opcode) {
1917 case SMB2_OP_IOCTL:
1918 case SMB2_OP_GETINFO:
1919 min_dyn_size = 0;
1920 break;
1921 case SMB2_OP_WRITE:
1922 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1923 if (req->smb1req->unread_bytes < min_dyn_size) {
1924 return NT_STATUS_INVALID_PARAMETER;
1927 min_dyn_size = 0;
1929 break;
1933 * Now check the expected body size,
1934 * where the last byte might be in the
1935 * dynamic section..
1937 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1938 return NT_STATUS_INVALID_PARAMETER;
1940 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1941 return NT_STATUS_INVALID_PARAMETER;
1944 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1946 body_size = SVAL(inbody, 0x00);
1947 if (body_size != expected_body_size) {
1948 return NT_STATUS_INVALID_PARAMETER;
1951 return NT_STATUS_OK;
1954 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1956 struct smbXsrv_connection *xconn = req->xconn;
1957 const struct smbd_smb2_dispatch_table *call = NULL;
1958 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1959 const uint8_t *inhdr;
1960 uint16_t opcode;
1961 uint32_t flags;
1962 uint64_t mid;
1963 NTSTATUS status;
1964 NTSTATUS session_status;
1965 uint32_t allowed_flags;
1966 NTSTATUS return_value;
1967 struct smbXsrv_session *x = NULL;
1968 bool signing_required = false;
1969 bool encryption_required = false;
1971 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1973 DO_PROFILE_INC(request);
1975 /* TODO: verify more things */
1977 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1978 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1979 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1980 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1981 smb2_opcode_name(opcode),
1982 (unsigned long long)mid));
1984 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1986 * once the protocol is negotiated
1987 * SMB2_OP_NEGPROT is not allowed anymore
1989 if (opcode == SMB2_OP_NEGPROT) {
1990 /* drop the connection */
1991 return NT_STATUS_INVALID_PARAMETER;
1993 } else {
1995 * if the protocol is not negotiated yet
1996 * only SMB2_OP_NEGPROT is allowed.
1998 if (opcode != SMB2_OP_NEGPROT) {
1999 /* drop the connection */
2000 return NT_STATUS_INVALID_PARAMETER;
2005 * Check if the client provided a valid session id,
2006 * if so smbd_smb2_request_check_session() calls
2007 * set_current_user_info().
2009 * As some command don't require a valid session id
2010 * we defer the check of the session_status
2012 session_status = smbd_smb2_request_check_session(req);
2013 x = req->session;
2014 if (x != NULL) {
2015 signing_required = x->global->signing_required;
2016 encryption_required = x->global->encryption_required;
2019 req->do_signing = false;
2020 req->do_encryption = false;
2021 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2022 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2023 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2025 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2026 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2027 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2028 (unsigned long long)x->global->session_wire_id,
2029 (unsigned long long)tf_session_id));
2031 * TODO: windows allows this...
2032 * should we drop the connection?
2034 * For now we just return ACCESS_DENIED
2035 * (Windows clients never trigger this)
2036 * and wait for an update of [MS-SMB2].
2038 return smbd_smb2_request_error(req,
2039 NT_STATUS_ACCESS_DENIED);
2042 req->do_encryption = true;
2045 if (encryption_required && !req->do_encryption) {
2046 return smbd_smb2_request_error(req,
2047 NT_STATUS_ACCESS_DENIED);
2050 call = smbd_smb2_call(opcode);
2051 if (call == NULL) {
2052 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2055 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2056 SMB2_HDR_FLAG_SIGNED |
2057 SMB2_HDR_FLAG_DFS;
2058 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2059 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2061 if (opcode == SMB2_OP_NEGPROT) {
2062 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2063 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2066 if (opcode == SMB2_OP_CANCEL) {
2067 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2069 if ((flags & ~allowed_flags) != 0) {
2070 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2073 if (flags & SMB2_HDR_FLAG_CHAINED) {
2075 * This check is mostly for giving the correct error code
2076 * for compounded requests.
2078 if (!NT_STATUS_IS_OK(session_status)) {
2079 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2081 } else {
2082 req->compat_chain_fsp = NULL;
2085 if (req->do_encryption) {
2086 signing_required = false;
2087 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2088 DATA_BLOB signing_key = data_blob_null;
2090 if (x == NULL) {
2092 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2093 * If the SMB2 header of the SMB2 NEGOTIATE
2094 * request has the SMB2_FLAGS_SIGNED bit set in the
2095 * Flags field, the server MUST fail the request
2096 * with STATUS_INVALID_PARAMETER.
2098 * Microsoft test tool checks this.
2101 if ((opcode == SMB2_OP_NEGPROT) &&
2102 (flags & SMB2_HDR_FLAG_SIGNED)) {
2103 status = NT_STATUS_INVALID_PARAMETER;
2104 } else {
2105 status = NT_STATUS_USER_SESSION_DELETED;
2107 return smbd_smb2_request_error(req, status);
2110 signing_key = smbd_smb2_signing_key(x, xconn);
2113 * If we have a signing key, we should
2114 * sign the response
2116 if (signing_key.length > 0) {
2117 req->do_signing = true;
2120 status = smb2_signing_check_pdu(signing_key,
2121 xconn->protocol,
2122 SMBD_SMB2_IN_HDR_IOV(req),
2123 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2124 if (!NT_STATUS_IS_OK(status)) {
2125 return smbd_smb2_request_error(req, status);
2129 * Now that we know the request was correctly signed
2130 * we have to sign the response too.
2132 req->do_signing = true;
2134 if (!NT_STATUS_IS_OK(session_status)) {
2135 return smbd_smb2_request_error(req, session_status);
2137 } else if (opcode == SMB2_OP_CANCEL) {
2138 /* Cancel requests are allowed to skip the signing */
2139 } else if (signing_required) {
2141 * If signing is required we try to sign
2142 * a possible error response
2144 req->do_signing = true;
2145 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2148 if (flags & SMB2_HDR_FLAG_CHAINED) {
2149 req->compound_related = true;
2152 if (call->need_session) {
2153 if (!NT_STATUS_IS_OK(session_status)) {
2154 return smbd_smb2_request_error(req, session_status);
2158 if (call->need_tcon) {
2159 SMB_ASSERT(call->need_session);
2162 * This call needs to be run as user.
2164 * smbd_smb2_request_check_tcon()
2165 * calls change_to_user() on success.
2167 status = smbd_smb2_request_check_tcon(req);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 return smbd_smb2_request_error(req, status);
2171 if (req->tcon->global->encryption_required) {
2172 encryption_required = true;
2174 if (encryption_required && !req->do_encryption) {
2175 return smbd_smb2_request_error(req,
2176 NT_STATUS_ACCESS_DENIED);
2180 if (call->fileid_ofs != 0) {
2181 size_t needed = call->fileid_ofs + 16;
2182 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2183 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2184 uint64_t file_id_persistent;
2185 uint64_t file_id_volatile;
2186 struct files_struct *fsp;
2188 SMB_ASSERT(call->need_tcon);
2190 if (needed > body_size) {
2191 return smbd_smb2_request_error(req,
2192 NT_STATUS_INVALID_PARAMETER);
2195 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2196 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2198 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2199 if (fsp == NULL) {
2200 if (!call->allow_invalid_fileid) {
2201 return smbd_smb2_request_error(req,
2202 NT_STATUS_FILE_CLOSED);
2205 if (file_id_persistent != UINT64_MAX) {
2206 return smbd_smb2_request_error(req,
2207 NT_STATUS_FILE_CLOSED);
2209 if (file_id_volatile != UINT64_MAX) {
2210 return smbd_smb2_request_error(req,
2211 NT_STATUS_FILE_CLOSED);
2216 if (call->as_root) {
2217 SMB_ASSERT(call->fileid_ofs == 0);
2218 /* This call needs to be run as root */
2219 change_to_root_user();
2220 } else {
2221 SMB_ASSERT(call->need_tcon);
2224 #define _INBYTES(_r) \
2225 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2227 switch (opcode) {
2228 case SMB2_OP_NEGPROT:
2229 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2230 req->profile, _INBYTES(req));
2231 return_value = smbd_smb2_request_process_negprot(req);
2232 break;
2234 case SMB2_OP_SESSSETUP:
2235 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2236 req->profile, _INBYTES(req));
2237 return_value = smbd_smb2_request_process_sesssetup(req);
2238 break;
2240 case SMB2_OP_LOGOFF:
2241 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2242 req->profile, _INBYTES(req));
2243 return_value = smbd_smb2_request_process_logoff(req);
2244 break;
2246 case SMB2_OP_TCON:
2247 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2248 req->profile, _INBYTES(req));
2249 return_value = smbd_smb2_request_process_tcon(req);
2250 break;
2252 case SMB2_OP_TDIS:
2253 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2254 req->profile, _INBYTES(req));
2255 return_value = smbd_smb2_request_process_tdis(req);
2256 break;
2258 case SMB2_OP_CREATE:
2259 if (req->subreq == NULL) {
2260 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2261 req->profile, _INBYTES(req));
2262 } else {
2263 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2265 return_value = smbd_smb2_request_process_create(req);
2266 break;
2268 case SMB2_OP_CLOSE:
2269 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2270 req->profile, _INBYTES(req));
2271 return_value = smbd_smb2_request_process_close(req);
2272 break;
2274 case SMB2_OP_FLUSH:
2275 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2276 req->profile, _INBYTES(req));
2277 return_value = smbd_smb2_request_process_flush(req);
2278 break;
2280 case SMB2_OP_READ:
2281 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2282 req->profile, _INBYTES(req));
2283 return_value = smbd_smb2_request_process_read(req);
2284 break;
2286 case SMB2_OP_WRITE:
2287 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2288 req->profile, _INBYTES(req));
2289 return_value = smbd_smb2_request_process_write(req);
2290 break;
2292 case SMB2_OP_LOCK:
2293 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2294 req->profile, _INBYTES(req));
2295 return_value = smbd_smb2_request_process_lock(req);
2296 break;
2298 case SMB2_OP_IOCTL:
2299 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2300 req->profile, _INBYTES(req));
2301 return_value = smbd_smb2_request_process_ioctl(req);
2302 break;
2304 case SMB2_OP_CANCEL:
2305 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2306 req->profile, _INBYTES(req));
2307 return_value = smbd_smb2_request_process_cancel(req);
2308 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2309 break;
2311 case SMB2_OP_KEEPALIVE:
2312 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2313 req->profile, _INBYTES(req));
2314 return_value = smbd_smb2_request_process_keepalive(req);
2315 break;
2317 case SMB2_OP_QUERY_DIRECTORY:
2318 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2319 req->profile, _INBYTES(req));
2320 return_value = smbd_smb2_request_process_query_directory(req);
2321 break;
2323 case SMB2_OP_NOTIFY:
2324 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2325 req->profile, _INBYTES(req));
2326 return_value = smbd_smb2_request_process_notify(req);
2327 break;
2329 case SMB2_OP_GETINFO:
2330 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2331 req->profile, _INBYTES(req));
2332 return_value = smbd_smb2_request_process_getinfo(req);
2333 break;
2335 case SMB2_OP_SETINFO:
2336 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2337 req->profile, _INBYTES(req));
2338 return_value = smbd_smb2_request_process_setinfo(req);
2339 break;
2341 case SMB2_OP_BREAK:
2342 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2343 req->profile, _INBYTES(req));
2344 return_value = smbd_smb2_request_process_break(req);
2345 break;
2347 default:
2348 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2349 break;
2351 return return_value;
2354 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2356 struct smbXsrv_connection *xconn = req->xconn;
2357 int first_idx = 1;
2358 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2359 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2360 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2361 NTSTATUS status;
2362 bool ok;
2364 req->subreq = NULL;
2365 TALLOC_FREE(req->async_te);
2367 if (req->do_encryption &&
2368 (firsttf->iov_len == 0) &&
2369 (req->first_key.length == 0) &&
2370 (req->session != NULL) &&
2371 (req->session->global->encryption_key.length != 0))
2373 DATA_BLOB encryption_key = req->session->global->encryption_key;
2374 uint8_t *tf;
2375 uint64_t session_id = req->session->global->session_wire_id;
2376 struct smbXsrv_session *x = req->session;
2377 uint64_t nonce_high;
2378 uint64_t nonce_low;
2380 nonce_high = x->nonce_high;
2381 nonce_low = x->nonce_low;
2383 x->nonce_low += 1;
2384 if (x->nonce_low == 0) {
2385 x->nonce_low += 1;
2386 x->nonce_high += 1;
2390 * We need to place the SMB2_TRANSFORM header before the
2391 * first SMB2 header
2395 * we need to remember the encryption key
2396 * and defer the signing/encryption until
2397 * we are sure that we do not change
2398 * the header again.
2400 req->first_key = data_blob_dup_talloc(req, encryption_key);
2401 if (req->first_key.data == NULL) {
2402 return NT_STATUS_NO_MEMORY;
2405 tf = talloc_zero_array(req, uint8_t,
2406 SMB2_TF_HDR_SIZE);
2407 if (tf == NULL) {
2408 return NT_STATUS_NO_MEMORY;
2411 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2412 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2413 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2414 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2416 firsttf->iov_base = (void *)tf;
2417 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2420 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2421 (req->last_key.length > 0) &&
2422 (firsttf->iov_len == 0))
2424 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2425 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2428 * As we are sure the header of the last request in the
2429 * compound chain will not change, we can to sign here
2430 * with the last signing key we remembered.
2432 status = smb2_signing_sign_pdu(req->last_key,
2433 xconn->protocol,
2434 lasthdr,
2435 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 return status;
2440 if (req->last_key.length > 0) {
2441 data_blob_clear_free(&req->last_key);
2444 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2445 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2447 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2449 if (req->current_idx < req->out.vector_count) {
2451 * We must process the remaining compound
2452 * SMB2 requests before any new incoming SMB2
2453 * requests. This is because incoming SMB2
2454 * requests may include a cancel for a
2455 * compound request we haven't processed
2456 * yet.
2458 struct tevent_immediate *im = tevent_create_immediate(req);
2459 if (!im) {
2460 return NT_STATUS_NO_MEMORY;
2463 if (req->do_signing && firsttf->iov_len == 0) {
2464 struct smbXsrv_session *x = req->session;
2465 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2468 * we need to remember the signing key
2469 * and defer the signing until
2470 * we are sure that we do not change
2471 * the header again.
2473 req->last_key = data_blob_dup_talloc(req, signing_key);
2474 if (req->last_key.data == NULL) {
2475 return NT_STATUS_NO_MEMORY;
2479 tevent_schedule_immediate(im,
2480 req->sconn->ev_ctx,
2481 smbd_smb2_request_dispatch_immediate,
2482 req);
2483 return NT_STATUS_OK;
2486 if (req->compound_related) {
2487 req->compound_related = false;
2490 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2491 if (!ok) {
2492 return NT_STATUS_INVALID_PARAMETER_MIX;
2495 /* Set credit for these operations (zero credits if this
2496 is a final reply for an async operation). */
2497 smb2_calculate_credits(req, req);
2500 * now check if we need to sign the current response
2502 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2503 status = smb2_signing_encrypt_pdu(req->first_key,
2504 xconn->smb2.server.cipher,
2505 firsttf,
2506 req->out.vector_count - first_idx);
2507 if (!NT_STATUS_IS_OK(status)) {
2508 return status;
2510 } else if (req->do_signing) {
2511 struct smbXsrv_session *x = req->session;
2512 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2514 status = smb2_signing_sign_pdu(signing_key,
2515 xconn->protocol,
2516 outhdr,
2517 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 return status;
2522 if (req->first_key.length > 0) {
2523 data_blob_clear_free(&req->first_key);
2526 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2527 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2528 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2529 /* Dynamic part is NULL. Chop it off,
2530 We're going to send it via sendfile. */
2531 req->out.vector_count -= 1;
2535 * We're done with this request -
2536 * move it off the "being processed" queue.
2538 DLIST_REMOVE(xconn->smb2.requests, req);
2540 req->queue_entry.mem_ctx = req;
2541 req->queue_entry.vector = req->out.vector;
2542 req->queue_entry.count = req->out.vector_count;
2543 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2544 xconn->smb2.send_queue_len++;
2546 status = smbd_smb2_flush_send_queue(xconn);
2547 if (!NT_STATUS_IS_OK(status)) {
2548 return status;
2551 return NT_STATUS_OK;
2554 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2556 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2557 struct tevent_immediate *im,
2558 void *private_data)
2560 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2561 struct smbd_smb2_request);
2562 struct smbXsrv_connection *xconn = req->xconn;
2563 NTSTATUS status;
2565 TALLOC_FREE(im);
2567 if (DEBUGLEVEL >= 10) {
2568 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2569 req->current_idx, req->in.vector_count));
2570 print_req_vectors(req);
2573 status = smbd_smb2_request_dispatch(req);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 smbd_server_connection_terminate(xconn, nt_errstr(status));
2576 return;
2579 status = smbd_smb2_request_next_incoming(xconn);
2580 if (!NT_STATUS_IS_OK(status)) {
2581 smbd_server_connection_terminate(xconn, nt_errstr(status));
2582 return;
2586 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2587 NTSTATUS status,
2588 DATA_BLOB body, DATA_BLOB *dyn,
2589 const char *location)
2591 uint8_t *outhdr;
2592 struct iovec *outbody_v;
2593 struct iovec *outdyn_v;
2594 uint32_t next_command_ofs;
2596 DEBUG(10,("smbd_smb2_request_done_ex: "
2597 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2598 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2599 dyn ? "yes": "no",
2600 (unsigned int)(dyn ? dyn->length : 0),
2601 location));
2603 if (body.length < 2) {
2604 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2607 if ((body.length % 2) != 0) {
2608 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2611 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2612 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2613 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2615 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2616 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2618 outbody_v->iov_base = (void *)body.data;
2619 outbody_v->iov_len = body.length;
2621 if (dyn) {
2622 outdyn_v->iov_base = (void *)dyn->data;
2623 outdyn_v->iov_len = dyn->length;
2624 } else {
2625 outdyn_v->iov_base = NULL;
2626 outdyn_v->iov_len = 0;
2629 /* see if we need to recalculate the offset to the next response */
2630 if (next_command_ofs > 0) {
2631 next_command_ofs = SMB2_HDR_BODY;
2632 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2633 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2636 if ((next_command_ofs % 8) != 0) {
2637 size_t pad_size = 8 - (next_command_ofs % 8);
2638 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2640 * if the dyn buffer is empty
2641 * we can use it to add padding
2643 uint8_t *pad;
2645 pad = talloc_zero_array(req,
2646 uint8_t, pad_size);
2647 if (pad == NULL) {
2648 return smbd_smb2_request_error(req,
2649 NT_STATUS_NO_MEMORY);
2652 outdyn_v->iov_base = (void *)pad;
2653 outdyn_v->iov_len = pad_size;
2654 } else {
2656 * For now we copy the dynamic buffer
2657 * and add the padding to the new buffer
2659 size_t old_size;
2660 uint8_t *old_dyn;
2661 size_t new_size;
2662 uint8_t *new_dyn;
2664 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2665 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2667 new_size = old_size + pad_size;
2668 new_dyn = talloc_zero_array(req,
2669 uint8_t, new_size);
2670 if (new_dyn == NULL) {
2671 return smbd_smb2_request_error(req,
2672 NT_STATUS_NO_MEMORY);
2675 memcpy(new_dyn, old_dyn, old_size);
2676 memset(new_dyn + old_size, 0, pad_size);
2678 outdyn_v->iov_base = (void *)new_dyn;
2679 outdyn_v->iov_len = new_size;
2681 next_command_ofs += pad_size;
2684 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2686 return smbd_smb2_request_reply(req);
2689 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2690 NTSTATUS status,
2691 DATA_BLOB *info,
2692 const char *location)
2694 struct smbXsrv_connection *xconn = req->xconn;
2695 DATA_BLOB body;
2696 DATA_BLOB _dyn;
2697 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2698 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2700 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2701 req->current_idx, nt_errstr(status), info ? " +info" : "",
2702 location));
2704 if (unread_bytes) {
2705 /* Recvfile error. Drain incoming socket. */
2706 size_t ret;
2708 errno = 0;
2709 ret = drain_socket(xconn->transport.sock, unread_bytes);
2710 if (ret != unread_bytes) {
2711 NTSTATUS error;
2713 if (errno == 0) {
2714 error = NT_STATUS_IO_DEVICE_ERROR;
2715 } else {
2716 error = map_nt_error_from_unix_common(errno);
2719 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2720 "ret[%u] errno[%d] => %s\n",
2721 (unsigned)unread_bytes,
2722 (unsigned)ret, errno, nt_errstr(error)));
2723 return error;
2727 body.data = outhdr + SMB2_HDR_BODY;
2728 body.length = 8;
2729 SSVAL(body.data, 0, 9);
2731 if (info) {
2732 SIVAL(body.data, 0x04, info->length);
2733 } else {
2734 /* Allocated size of req->out.vector[i].iov_base
2735 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2736 * 1 byte without having to do an alloc.
2738 info = &_dyn;
2739 info->data = ((uint8_t *)outhdr) +
2740 OUTVEC_ALLOC_SIZE - 1;
2741 info->length = 1;
2742 SCVAL(info->data, 0, 0);
2746 * Note: Even if there is an error, continue to process the request.
2747 * per MS-SMB2.
2750 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2754 struct smbd_smb2_send_break_state {
2755 struct smbd_smb2_send_queue queue_entry;
2756 uint8_t nbt_hdr[NBT_HDR_SIZE];
2757 uint8_t tf[SMB2_TF_HDR_SIZE];
2758 uint8_t hdr[SMB2_HDR_BODY];
2759 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2760 uint8_t body[1];
2763 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2764 struct smbXsrv_session *session,
2765 struct smbXsrv_tcon *tcon,
2766 const uint8_t *body,
2767 size_t body_len)
2769 struct smbd_smb2_send_break_state *state;
2770 bool do_encryption = false;
2771 uint64_t session_wire_id = 0;
2772 uint64_t nonce_high = 0;
2773 uint64_t nonce_low = 0;
2774 NTSTATUS status;
2775 size_t statelen;
2776 bool ok;
2778 if (session != NULL) {
2779 session_wire_id = session->global->session_wire_id;
2780 do_encryption = session->global->encryption_required;
2781 if (tcon->global->encryption_required) {
2782 do_encryption = true;
2786 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2787 body_len;
2789 state = talloc_zero_size(xconn, statelen);
2790 if (state == NULL) {
2791 return NT_STATUS_NO_MEMORY;
2793 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2795 if (do_encryption) {
2796 nonce_high = session->nonce_high;
2797 nonce_low = session->nonce_low;
2799 session->nonce_low += 1;
2800 if (session->nonce_low == 0) {
2801 session->nonce_low += 1;
2802 session->nonce_high += 1;
2806 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2807 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2808 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2809 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2811 SIVAL(state->hdr, 0, SMB2_MAGIC);
2812 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2813 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2814 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2815 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2816 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2817 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2818 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2819 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2820 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2821 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2822 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2823 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2825 state->vector[0] = (struct iovec) {
2826 .iov_base = state->nbt_hdr,
2827 .iov_len = sizeof(state->nbt_hdr)
2830 if (do_encryption) {
2831 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2832 .iov_base = state->tf,
2833 .iov_len = sizeof(state->tf)
2835 } else {
2836 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2837 .iov_base = NULL,
2838 .iov_len = 0
2842 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2843 .iov_base = state->hdr,
2844 .iov_len = sizeof(state->hdr)
2847 memcpy(state->body, body, body_len);
2849 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2850 .iov_base = state->body,
2851 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2855 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2858 ok = smb2_setup_nbt_length(state->vector,
2859 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2860 if (!ok) {
2861 return NT_STATUS_INVALID_PARAMETER_MIX;
2864 if (do_encryption) {
2865 DATA_BLOB encryption_key = session->global->encryption_key;
2867 status = smb2_signing_encrypt_pdu(encryption_key,
2868 xconn->smb2.server.cipher,
2869 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2870 SMBD_SMB2_NUM_IOV_PER_REQ);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 return status;
2876 state->queue_entry.mem_ctx = state;
2877 state->queue_entry.vector = state->vector;
2878 state->queue_entry.count = ARRAY_SIZE(state->vector);
2879 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2880 xconn->smb2.send_queue_len++;
2882 status = smbd_smb2_flush_send_queue(xconn);
2883 if (!NT_STATUS_IS_OK(status)) {
2884 return status;
2887 return NT_STATUS_OK;
2890 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2891 struct smbXsrv_session *session,
2892 struct smbXsrv_tcon *tcon,
2893 struct smbXsrv_open *op,
2894 uint8_t oplock_level)
2896 uint8_t body[0x18];
2898 SSVAL(body, 0x00, sizeof(body));
2899 SCVAL(body, 0x02, oplock_level);
2900 SCVAL(body, 0x03, 0); /* reserved */
2901 SIVAL(body, 0x04, 0); /* reserved */
2902 SBVAL(body, 0x08, op->global->open_persistent_id);
2903 SBVAL(body, 0x10, op->global->open_volatile_id);
2905 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2908 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
2909 uint16_t new_epoch,
2910 uint32_t lease_flags,
2911 struct smb2_lease_key *lease_key,
2912 uint32_t current_lease_state,
2913 uint32_t new_lease_state)
2915 uint8_t body[0x2c];
2917 SSVAL(body, 0x00, sizeof(body));
2918 SSVAL(body, 0x02, new_epoch);
2919 SIVAL(body, 0x04, lease_flags);
2920 SBVAL(body, 0x08, lease_key->data[0]);
2921 SBVAL(body, 0x10, lease_key->data[1]);
2922 SIVAL(body, 0x18, current_lease_state);
2923 SIVAL(body, 0x1c, new_lease_state);
2924 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
2925 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2926 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2928 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
2931 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2933 NTSTATUS status;
2934 uint32_t flags;
2935 uint64_t file_id_persistent;
2936 uint64_t file_id_volatile;
2937 struct smbXsrv_open *op = NULL;
2938 struct files_struct *fsp = NULL;
2939 const uint8_t *body = NULL;
2942 * This is only called with a pktbuf
2943 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2944 * bytes
2947 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2948 /* Transform header. Cannot recvfile. */
2949 return false;
2951 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2952 /* Not SMB2. Normal error path will cope. */
2953 return false;
2955 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2956 /* Not SMB2. Normal error path will cope. */
2957 return false;
2959 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2960 /* Needs to be a WRITE. */
2961 return false;
2963 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2964 /* Chained. Cannot recvfile. */
2965 return false;
2967 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2968 if (flags & SMB2_HDR_FLAG_CHAINED) {
2969 /* Chained. Cannot recvfile. */
2970 return false;
2972 if (flags & SMB2_HDR_FLAG_SIGNED) {
2973 /* Signed. Cannot recvfile. */
2974 return false;
2977 body = &state->pktbuf[SMB2_HDR_BODY];
2979 file_id_persistent = BVAL(body, 0x10);
2980 file_id_volatile = BVAL(body, 0x18);
2982 status = smb2srv_open_lookup(state->req->xconn,
2983 file_id_persistent,
2984 file_id_volatile,
2985 0, /* now */
2986 &op);
2987 if (!NT_STATUS_IS_OK(status)) {
2988 return false;
2991 fsp = op->compat;
2992 if (fsp == NULL) {
2993 return false;
2995 if (fsp->conn == NULL) {
2996 return false;
2999 if (IS_IPC(fsp->conn)) {
3000 return false;
3002 if (IS_PRINT(fsp->conn)) {
3003 return false;
3006 DEBUG(10,("Doing recvfile write len = %u\n",
3007 (unsigned int)(state->pktfull - state->pktlen)));
3009 return true;
3012 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3014 struct smbd_server_connection *sconn = xconn->client->sconn;
3015 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3016 size_t max_send_queue_len;
3017 size_t cur_send_queue_len;
3019 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3021 * we're not supposed to do any io
3023 return NT_STATUS_OK;
3026 if (state->req != NULL) {
3028 * if there is already a tstream_readv_pdu
3029 * pending, we are done.
3031 return NT_STATUS_OK;
3034 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3035 cur_send_queue_len = xconn->smb2.send_queue_len;
3037 if (cur_send_queue_len > max_send_queue_len) {
3039 * if we have a lot of requests to send,
3040 * we wait until they are on the wire until we
3041 * ask for the next request.
3043 return NT_STATUS_OK;
3046 /* ask for the next request */
3047 ZERO_STRUCTP(state);
3048 state->req = smbd_smb2_request_allocate(xconn);
3049 if (state->req == NULL) {
3050 return NT_STATUS_NO_MEMORY;
3052 state->req->sconn = sconn;
3053 state->req->xconn = xconn;
3054 state->min_recv_size = lp_min_receive_file_size();
3056 TEVENT_FD_READABLE(xconn->transport.fde);
3058 return NT_STATUS_OK;
3061 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3062 const uint8_t *inpdu, size_t size)
3064 struct smbd_server_connection *sconn = xconn->client->sconn;
3065 NTSTATUS status;
3066 struct smbd_smb2_request *req = NULL;
3068 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3069 (unsigned int)size));
3071 status = smbd_initialize_smb2(xconn);
3072 if (!NT_STATUS_IS_OK(status)) {
3073 smbd_server_connection_terminate(xconn, nt_errstr(status));
3074 return;
3077 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3078 if (!NT_STATUS_IS_OK(status)) {
3079 smbd_server_connection_terminate(xconn, nt_errstr(status));
3080 return;
3083 status = smbd_smb2_request_validate(req);
3084 if (!NT_STATUS_IS_OK(status)) {
3085 smbd_server_connection_terminate(xconn, nt_errstr(status));
3086 return;
3089 status = smbd_smb2_request_setup_out(req);
3090 if (!NT_STATUS_IS_OK(status)) {
3091 smbd_server_connection_terminate(xconn, nt_errstr(status));
3092 return;
3095 #ifdef WITH_PROFILE
3097 * this was already counted at the SMB1 layer =>
3098 * smbd_smb2_request_dispatch() should not count it twice.
3100 if (profile_p->values.request_stats.count > 0) {
3101 profile_p->values.request_stats.count--;
3103 #endif
3104 status = smbd_smb2_request_dispatch(req);
3105 if (!NT_STATUS_IS_OK(status)) {
3106 smbd_server_connection_terminate(xconn, nt_errstr(status));
3107 return;
3110 status = smbd_smb2_request_next_incoming(xconn);
3111 if (!NT_STATUS_IS_OK(status)) {
3112 smbd_server_connection_terminate(xconn, nt_errstr(status));
3113 return;
3116 sconn->num_requests++;
3119 static int socket_error_from_errno(int ret,
3120 int sys_errno,
3121 bool *retry)
3123 *retry = false;
3125 if (ret >= 0) {
3126 return 0;
3129 if (ret != -1) {
3130 return EIO;
3133 if (sys_errno == 0) {
3134 return EIO;
3137 if (sys_errno == EINTR) {
3138 *retry = true;
3139 return sys_errno;
3142 if (sys_errno == EINPROGRESS) {
3143 *retry = true;
3144 return sys_errno;
3147 if (sys_errno == EAGAIN) {
3148 *retry = true;
3149 return sys_errno;
3152 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3153 if (sys_errno == ENOMEM) {
3154 *retry = true;
3155 return sys_errno;
3158 #ifdef EWOULDBLOCK
3159 #if EWOULDBLOCK != EAGAIN
3160 if (sys_errno == EWOULDBLOCK) {
3161 *retry = true;
3162 return sys_errno;
3164 #endif
3165 #endif
3167 return sys_errno;
3170 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3172 int ret;
3173 int err;
3174 bool retry;
3176 if (xconn->smb2.send_queue == NULL) {
3177 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3178 return NT_STATUS_OK;
3181 while (xconn->smb2.send_queue != NULL) {
3182 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3183 bool ok;
3185 if (e->sendfile_header != NULL) {
3186 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3187 size_t size = 0;
3188 size_t i = 0;
3189 uint8_t *buf;
3191 for (i=0; i < e->count; i++) {
3192 size += e->vector[i].iov_len;
3195 if (size <= e->sendfile_header->length) {
3196 buf = e->sendfile_header->data;
3197 } else {
3198 buf = talloc_array(e->mem_ctx, uint8_t, size);
3199 if (buf == NULL) {
3200 return NT_STATUS_NO_MEMORY;
3204 size = 0;
3205 for (i=0; i < e->count; i++) {
3206 memcpy(buf+size,
3207 e->vector[i].iov_base,
3208 e->vector[i].iov_len);
3209 size += e->vector[i].iov_len;
3212 e->sendfile_header->data = buf;
3213 e->sendfile_header->length = size;
3214 e->sendfile_status = &status;
3215 e->count = 0;
3217 xconn->smb2.send_queue_len--;
3218 DLIST_REMOVE(xconn->smb2.send_queue, e);
3220 * This triggers the sendfile path via
3221 * the destructor.
3223 talloc_free(e->mem_ctx);
3225 if (!NT_STATUS_IS_OK(status)) {
3226 return status;
3228 continue;
3231 ret = writev(xconn->transport.sock, e->vector, e->count);
3232 if (ret == 0) {
3233 /* propagate end of file */
3234 return NT_STATUS_INTERNAL_ERROR;
3236 err = socket_error_from_errno(ret, errno, &retry);
3237 if (retry) {
3238 /* retry later */
3239 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3240 return NT_STATUS_OK;
3242 if (err != 0) {
3243 return map_nt_error_from_unix_common(err);
3246 ok = iov_advance(&e->vector, &e->count, ret);
3247 if (!ok) {
3248 return NT_STATUS_INTERNAL_ERROR;
3251 if (e->count > 0) {
3252 /* we have more to write */
3253 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3254 return NT_STATUS_OK;
3257 xconn->smb2.send_queue_len--;
3258 DLIST_REMOVE(xconn->smb2.send_queue, e);
3259 talloc_free(e->mem_ctx);
3262 return NT_STATUS_OK;
3265 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3266 uint16_t fde_flags)
3268 struct smbd_server_connection *sconn = xconn->client->sconn;
3269 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3270 struct smbd_smb2_request *req = NULL;
3271 size_t min_recvfile_size = UINT32_MAX;
3272 int ret;
3273 int err;
3274 bool retry;
3275 NTSTATUS status;
3276 NTTIME now;
3278 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3280 * we're not supposed to do any io
3282 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3283 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3284 return NT_STATUS_OK;
3287 if (fde_flags & TEVENT_FD_WRITE) {
3288 status = smbd_smb2_flush_send_queue(xconn);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 return status;
3294 if (!(fde_flags & TEVENT_FD_READ)) {
3295 return NT_STATUS_OK;
3298 if (state->req == NULL) {
3299 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3300 return NT_STATUS_OK;
3303 again:
3304 if (!state->hdr.done) {
3305 state->hdr.done = true;
3307 state->vector.iov_base = (void *)state->hdr.nbt;
3308 state->vector.iov_len = NBT_HDR_SIZE;
3311 ret = readv(xconn->transport.sock, &state->vector, 1);
3312 if (ret == 0) {
3313 /* propagate end of file */
3314 return NT_STATUS_END_OF_FILE;
3316 err = socket_error_from_errno(ret, errno, &retry);
3317 if (retry) {
3318 /* retry later */
3319 TEVENT_FD_READABLE(xconn->transport.fde);
3320 return NT_STATUS_OK;
3322 if (err != 0) {
3323 return map_nt_error_from_unix_common(err);
3326 if (ret < state->vector.iov_len) {
3327 uint8_t *base;
3328 base = (uint8_t *)state->vector.iov_base;
3329 base += ret;
3330 state->vector.iov_base = (void *)base;
3331 state->vector.iov_len -= ret;
3332 /* we have more to read */
3333 TEVENT_FD_READABLE(xconn->transport.fde);
3334 return NT_STATUS_OK;
3337 if (state->pktlen > 0) {
3338 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3340 * Not a possible receivefile write.
3341 * Read the rest of the data.
3343 state->doing_receivefile = false;
3345 state->pktbuf = talloc_realloc(state->req,
3346 state->pktbuf,
3347 uint8_t,
3348 state->pktfull);
3349 if (state->pktbuf == NULL) {
3350 return NT_STATUS_NO_MEMORY;
3353 state->vector.iov_base = (void *)(state->pktbuf +
3354 state->pktlen);
3355 state->vector.iov_len = (state->pktfull -
3356 state->pktlen);
3358 state->pktlen = state->pktfull;
3359 goto again;
3363 * Either this is a receivefile write so we've
3364 * done a short read, or if not we have all the data.
3366 goto got_full;
3370 * Now we analyze the NBT header
3372 if (state->hdr.nbt[0] != 0x00) {
3373 state->min_recv_size = 0;
3375 state->pktfull = smb2_len(state->hdr.nbt);
3376 if (state->pktfull == 0) {
3377 goto got_full;
3380 if (state->min_recv_size != 0) {
3381 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3382 min_recvfile_size += state->min_recv_size;
3385 if (state->pktfull > min_recvfile_size) {
3387 * Might be a receivefile write. Read the SMB2 HEADER +
3388 * SMB2_WRITE header first. Set 'doing_receivefile'
3389 * as we're *attempting* receivefile write. If this
3390 * turns out not to be a SMB2_WRITE request or otherwise
3391 * not suitable then we'll just read the rest of the data
3392 * the next time this function is called.
3394 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3395 state->doing_receivefile = true;
3396 } else {
3397 state->pktlen = state->pktfull;
3400 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3401 if (state->pktbuf == NULL) {
3402 return NT_STATUS_NO_MEMORY;
3405 state->vector.iov_base = (void *)state->pktbuf;
3406 state->vector.iov_len = state->pktlen;
3408 goto again;
3410 got_full:
3412 if (state->hdr.nbt[0] != 0x00) {
3413 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3414 state->hdr.nbt[0]));
3416 req = state->req;
3417 ZERO_STRUCTP(state);
3418 state->req = req;
3419 state->min_recv_size = lp_min_receive_file_size();
3420 req = NULL;
3421 goto again;
3424 req = state->req;
3425 state->req = NULL;
3427 req->request_time = timeval_current();
3428 now = timeval_to_nttime(&req->request_time);
3430 status = smbd_smb2_inbuf_parse_compound(xconn,
3431 now,
3432 state->pktbuf,
3433 state->pktlen,
3434 req,
3435 &req->in.vector,
3436 &req->in.vector_count);
3437 if (!NT_STATUS_IS_OK(status)) {
3438 return status;
3441 if (state->doing_receivefile) {
3442 req->smb1req = talloc_zero(req, struct smb_request);
3443 if (req->smb1req == NULL) {
3444 return NT_STATUS_NO_MEMORY;
3446 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3449 ZERO_STRUCTP(state);
3451 req->current_idx = 1;
3453 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3454 req->current_idx, req->in.vector_count));
3456 status = smbd_smb2_request_validate(req);
3457 if (!NT_STATUS_IS_OK(status)) {
3458 return status;
3461 status = smbd_smb2_request_setup_out(req);
3462 if (!NT_STATUS_IS_OK(status)) {
3463 return status;
3466 status = smbd_smb2_request_dispatch(req);
3467 if (!NT_STATUS_IS_OK(status)) {
3468 return status;
3471 sconn->num_requests++;
3473 /* The timeout_processing function isn't run nearly
3474 often enough to implement 'max log size' without
3475 overrunning the size of the file by many megabytes.
3476 This is especially true if we are running at debug
3477 level 10. Checking every 50 SMB2s is a nice
3478 tradeoff of performance vs log file size overrun. */
3480 if ((sconn->num_requests % 50) == 0 &&
3481 need_to_check_log_size()) {
3482 change_to_root_user();
3483 check_log_size();
3486 status = smbd_smb2_request_next_incoming(xconn);
3487 if (!NT_STATUS_IS_OK(status)) {
3488 return status;
3491 return NT_STATUS_OK;
3494 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3495 struct tevent_fd *fde,
3496 uint16_t flags,
3497 void *private_data)
3499 struct smbXsrv_connection *xconn =
3500 talloc_get_type_abort(private_data,
3501 struct smbXsrv_connection);
3502 NTSTATUS status;
3504 status = smbd_smb2_io_handler(xconn, flags);
3505 if (!NT_STATUS_IS_OK(status)) {
3506 smbd_server_connection_terminate(xconn, nt_errstr(status));
3507 return;