ctdb-daemon: Fix typo in debug message
[Samba.git] / source3 / smbd / smb2_server.c
blob9e5eff7cb6007e16dadb29954ec30da95ecc05de
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"
33 #include "lib/crypto/sha512.h"
35 static void smbd_smb2_connection_handler(struct tevent_context *ev,
36 struct tevent_fd *fde,
37 uint16_t flags,
38 void *private_data);
39 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
41 static const struct smbd_smb2_dispatch_table {
42 uint16_t opcode;
43 const char *name;
44 bool need_session;
45 bool need_tcon;
46 bool as_root;
47 uint16_t fileid_ofs;
48 bool allow_invalid_fileid;
49 } smbd_smb2_table[] = {
50 #define _OP(o) .opcode = o, .name = #o
52 _OP(SMB2_OP_NEGPROT),
53 .as_root = true,
54 },{
55 _OP(SMB2_OP_SESSSETUP),
56 .as_root = true,
57 },{
58 _OP(SMB2_OP_LOGOFF),
59 .need_session = true,
60 .as_root = true,
61 },{
62 _OP(SMB2_OP_TCON),
63 .need_session = true,
65 * This call needs to be run as root.
67 * smbd_smb2_request_process_tcon()
68 * calls make_connection_snum(), which will call
69 * change_to_user(), when needed.
71 .as_root = true,
72 },{
73 _OP(SMB2_OP_TDIS),
74 .need_session = true,
75 .need_tcon = true,
76 .as_root = true,
77 },{
78 _OP(SMB2_OP_CREATE),
79 .need_session = true,
80 .need_tcon = true,
81 },{
82 _OP(SMB2_OP_CLOSE),
83 .need_session = true,
84 .need_tcon = true,
85 .fileid_ofs = 0x08,
86 },{
87 _OP(SMB2_OP_FLUSH),
88 .need_session = true,
89 .need_tcon = true,
90 .fileid_ofs = 0x08,
91 },{
92 _OP(SMB2_OP_READ),
93 .need_session = true,
94 .need_tcon = true,
95 .fileid_ofs = 0x10,
96 },{
97 _OP(SMB2_OP_WRITE),
98 .need_session = true,
99 .need_tcon = true,
100 .fileid_ofs = 0x10,
102 _OP(SMB2_OP_LOCK),
103 .need_session = true,
104 .need_tcon = true,
105 .fileid_ofs = 0x08,
107 _OP(SMB2_OP_IOCTL),
108 .need_session = true,
109 .need_tcon = true,
110 .fileid_ofs = 0x08,
111 .allow_invalid_fileid = true,
113 _OP(SMB2_OP_CANCEL),
114 .as_root = true,
116 _OP(SMB2_OP_KEEPALIVE),
117 .as_root = true,
119 _OP(SMB2_OP_QUERY_DIRECTORY),
120 .need_session = true,
121 .need_tcon = true,
122 .fileid_ofs = 0x08,
124 _OP(SMB2_OP_NOTIFY),
125 .need_session = true,
126 .need_tcon = true,
127 .fileid_ofs = 0x08,
129 _OP(SMB2_OP_GETINFO),
130 .need_session = true,
131 .need_tcon = true,
132 .fileid_ofs = 0x18,
134 _OP(SMB2_OP_SETINFO),
135 .need_session = true,
136 .need_tcon = true,
137 .fileid_ofs = 0x10,
139 _OP(SMB2_OP_BREAK),
140 .need_session = true,
141 .need_tcon = true,
143 * we do not set
144 * .fileid_ofs here
145 * as LEASE breaks does not
146 * have a file id
151 const char *smb2_opcode_name(uint16_t opcode)
153 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
154 return "Bad SMB2 opcode";
156 return smbd_smb2_table[opcode].name;
159 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
161 const struct smbd_smb2_dispatch_table *ret = NULL;
163 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
164 return NULL;
167 ret = &smbd_smb2_table[opcode];
169 SMB_ASSERT(ret->opcode == opcode);
171 return ret;
174 static void print_req_vectors(const struct smbd_smb2_request *req)
176 int i;
178 for (i = 0; i < req->in.vector_count; i++) {
179 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
180 (unsigned int)i,
181 (unsigned int)req->in.vector[i].iov_len);
183 for (i = 0; i < req->out.vector_count; i++) {
184 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
185 (unsigned int)i,
186 (unsigned int)req->out.vector[i].iov_len);
190 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
192 if (size < (4 + SMB2_HDR_BODY)) {
193 return false;
196 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
197 return false;
200 return true;
203 static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
205 TALLOC_FREE(xconn->transport.fde);
207 xconn->smb2.credits.seq_low = 0;
208 xconn->smb2.credits.seq_range = 1;
209 xconn->smb2.credits.granted = 1;
210 xconn->smb2.credits.max = lp_smb2_max_credits();
211 xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
212 xconn->smb2.credits.max);
213 if (xconn->smb2.credits.bitmap == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 xconn->transport.fde = tevent_add_fd(xconn->ev_ctx,
218 xconn,
219 xconn->transport.sock,
220 TEVENT_FD_READ,
221 smbd_smb2_connection_handler,
222 xconn);
223 if (xconn->transport.fde == NULL) {
224 return NT_STATUS_NO_MEMORY;
227 /* Ensure child is set to non-blocking mode */
228 set_blocking(xconn->transport.sock, false);
229 return NT_STATUS_OK;
232 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
233 #define _smb2_setlen(_buf,len) do { \
234 uint8_t *buf = (uint8_t *)_buf; \
235 buf[0] = 0; \
236 buf[1] = ((len)&0xFF0000)>>16; \
237 buf[2] = ((len)&0xFF00)>>8; \
238 buf[3] = (len)&0xFF; \
239 } while (0)
241 static bool smb2_setup_nbt_length(struct iovec *vector, int count)
243 ssize_t len;
245 if (count == 0) {
246 return false;
249 len = iov_buflen(vector+1, count-1);
251 if ((len == -1) || (len > 0xFFFFFF)) {
252 return false;
255 _smb2_setlen(vector[0].iov_base, len);
256 return true;
259 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
261 if (req->first_key.length > 0) {
262 data_blob_clear_free(&req->first_key);
264 if (req->last_key.length > 0) {
265 data_blob_clear_free(&req->last_key);
267 return 0;
270 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
272 TALLOC_CTX *mem_pool;
273 struct smbd_smb2_request *req;
275 #if 0
276 /* Enable this to find subtle valgrind errors. */
277 mem_pool = talloc_init("smbd_smb2_request_allocate");
278 #else
279 mem_pool = talloc_tos();
280 #endif
281 if (mem_pool == NULL) {
282 return NULL;
285 req = talloc_zero(mem_pool, struct smbd_smb2_request);
286 if (req == NULL) {
287 talloc_free(mem_pool);
288 return NULL;
290 talloc_reparent(mem_pool, mem_ctx, req);
291 #if 0
292 TALLOC_FREE(mem_pool);
293 #endif
295 req->last_session_id = UINT64_MAX;
296 req->last_tid = UINT32_MAX;
298 talloc_set_destructor(req, smbd_smb2_request_destructor);
300 return req;
303 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
304 NTTIME now,
305 uint8_t *buf,
306 size_t buflen,
307 struct smbd_smb2_request *req,
308 struct iovec **piov,
309 int *pnum_iov)
311 TALLOC_CTX *mem_ctx = req;
312 struct iovec *iov;
313 int num_iov = 1;
314 size_t taken = 0;
315 uint8_t *first_hdr = buf;
316 size_t verified_buflen = 0;
317 uint8_t *tf = NULL;
318 size_t tf_len = 0;
321 * Note: index '0' is reserved for the transport protocol
323 iov = req->in._vector;
325 while (taken < buflen) {
326 size_t len = buflen - taken;
327 uint8_t *hdr = first_hdr + taken;
328 struct iovec *cur;
329 size_t full_size;
330 size_t next_command_ofs;
331 uint16_t body_size;
332 uint8_t *body = NULL;
333 uint32_t dyn_size;
334 uint8_t *dyn = NULL;
335 struct iovec *iov_alloc = NULL;
337 if (iov != req->in._vector) {
338 iov_alloc = iov;
341 if (verified_buflen > taken) {
342 len = verified_buflen - taken;
343 } else {
344 tf = NULL;
345 tf_len = 0;
348 if (len < 4) {
349 DEBUG(10, ("%d bytes left, expected at least %d\n",
350 (int)len, 4));
351 goto inval;
353 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
354 struct smbXsrv_session *s = NULL;
355 uint64_t uid;
356 struct iovec tf_iov[2];
357 NTSTATUS status;
358 size_t enc_len;
360 if (xconn->protocol < PROTOCOL_SMB2_24) {
361 DEBUG(10, ("Got SMB2_TRANSFORM header, "
362 "but dialect[0x%04X] is used\n",
363 xconn->smb2.server.dialect));
364 goto inval;
367 if (xconn->smb2.server.cipher == 0) {
368 DEBUG(10, ("Got SMB2_TRANSFORM header, "
369 "but not negotiated "
370 "client[0x%08X] server[0x%08X]\n",
371 xconn->smb2.client.capabilities,
372 xconn->smb2.server.capabilities));
373 goto inval;
376 if (len < SMB2_TF_HDR_SIZE) {
377 DEBUG(1, ("%d bytes left, expected at least %d\n",
378 (int)len, SMB2_TF_HDR_SIZE));
379 goto inval;
381 tf = hdr;
382 tf_len = SMB2_TF_HDR_SIZE;
383 taken += tf_len;
385 hdr = first_hdr + taken;
386 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
387 uid = BVAL(tf, SMB2_TF_SESSION_ID);
389 if (len < SMB2_TF_HDR_SIZE + enc_len) {
390 DEBUG(1, ("%d bytes left, expected at least %d\n",
391 (int)len,
392 (int)(SMB2_TF_HDR_SIZE + enc_len)));
393 goto inval;
396 status = smb2srv_session_lookup(xconn, uid, now, &s);
397 if (s == NULL) {
398 DEBUG(1, ("invalid session[%llu] in "
399 "SMB2_TRANSFORM header\n",
400 (unsigned long long)uid));
401 TALLOC_FREE(iov_alloc);
402 return NT_STATUS_USER_SESSION_DELETED;
405 tf_iov[0].iov_base = (void *)tf;
406 tf_iov[0].iov_len = tf_len;
407 tf_iov[1].iov_base = (void *)hdr;
408 tf_iov[1].iov_len = enc_len;
410 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
411 xconn->smb2.server.cipher,
412 tf_iov, 2);
413 if (!NT_STATUS_IS_OK(status)) {
414 TALLOC_FREE(iov_alloc);
415 return status;
418 verified_buflen = taken + enc_len;
419 len = enc_len;
423 * We need the header plus the body length field
426 if (len < SMB2_HDR_BODY + 2) {
427 DEBUG(10, ("%d bytes left, expected at least %d\n",
428 (int)len, SMB2_HDR_BODY));
429 goto inval;
431 if (IVAL(hdr, 0) != SMB2_MAGIC) {
432 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
433 IVAL(hdr, 0)));
434 goto inval;
436 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
437 DEBUG(10, ("Got HDR len %d, expected %d\n",
438 SVAL(hdr, 4), SMB2_HDR_BODY));
439 goto inval;
442 full_size = len;
443 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
444 body_size = SVAL(hdr, SMB2_HDR_BODY);
446 if (next_command_ofs != 0) {
447 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
448 goto inval;
450 if (next_command_ofs > full_size) {
451 goto inval;
453 full_size = next_command_ofs;
455 if (body_size < 2) {
456 goto inval;
458 body_size &= 0xfffe;
460 if (body_size > (full_size - SMB2_HDR_BODY)) {
462 * let the caller handle the error
464 body_size = full_size - SMB2_HDR_BODY;
466 body = hdr + SMB2_HDR_BODY;
467 dyn = body + body_size;
468 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
470 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
471 struct iovec *iov_tmp = NULL;
473 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
474 struct iovec,
475 num_iov +
476 SMBD_SMB2_NUM_IOV_PER_REQ);
477 if (iov_tmp == NULL) {
478 TALLOC_FREE(iov_alloc);
479 return NT_STATUS_NO_MEMORY;
482 if (iov_alloc == NULL) {
483 memcpy(iov_tmp,
484 req->in._vector,
485 sizeof(req->in._vector));
488 iov = iov_tmp;
490 cur = &iov[num_iov];
491 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
493 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
494 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
495 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
496 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
497 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
498 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
499 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
500 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
502 taken += full_size;
505 *piov = iov;
506 *pnum_iov = num_iov;
507 return NT_STATUS_OK;
509 inval:
510 if (iov != req->in._vector) {
511 TALLOC_FREE(iov);
513 return NT_STATUS_INVALID_PARAMETER;
516 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
517 const uint8_t *_inpdu, size_t size,
518 struct smbd_smb2_request **_req)
520 struct smbd_server_connection *sconn = xconn->client->sconn;
521 struct smbd_smb2_request *req;
522 uint32_t protocol_version;
523 uint8_t *inpdu = NULL;
524 const uint8_t *inhdr = NULL;
525 uint16_t cmd;
526 uint32_t next_command_ofs;
527 NTSTATUS status;
528 NTTIME now;
530 if (size < (SMB2_HDR_BODY + 2)) {
531 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
532 return NT_STATUS_INVALID_PARAMETER;
535 inhdr = _inpdu;
537 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
538 if (protocol_version != SMB2_MAGIC) {
539 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
540 protocol_version));
541 return NT_STATUS_INVALID_PARAMETER;
544 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
545 if (cmd != SMB2_OP_NEGPROT) {
546 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
547 cmd));
548 return NT_STATUS_INVALID_PARAMETER;
551 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
552 if (next_command_ofs != 0) {
553 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
554 next_command_ofs));
555 return NT_STATUS_INVALID_PARAMETER;
558 req = smbd_smb2_request_allocate(xconn);
559 if (req == NULL) {
560 return NT_STATUS_NO_MEMORY;
562 req->sconn = sconn;
563 req->xconn = xconn;
565 inpdu = talloc_memdup(req, _inpdu, size);
566 if (inpdu == NULL) {
567 return NT_STATUS_NO_MEMORY;
570 req->request_time = timeval_current();
571 now = timeval_to_nttime(&req->request_time);
573 status = smbd_smb2_inbuf_parse_compound(xconn,
574 now,
575 inpdu,
576 size,
577 req, &req->in.vector,
578 &req->in.vector_count);
579 if (!NT_STATUS_IS_OK(status)) {
580 TALLOC_FREE(req);
581 return status;
584 req->current_idx = 1;
586 *_req = req;
587 return NT_STATUS_OK;
590 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
591 uint64_t message_id, uint64_t seq_id)
593 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
594 unsigned int offset;
595 uint64_t seq_tmp;
597 seq_tmp = xconn->smb2.credits.seq_low;
598 if (seq_id < seq_tmp) {
599 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
600 "%llu (sequence id %llu) "
601 "(granted = %u, low = %llu, range = %u)\n",
602 (unsigned long long)message_id,
603 (unsigned long long)seq_id,
604 (unsigned int)xconn->smb2.credits.granted,
605 (unsigned long long)xconn->smb2.credits.seq_low,
606 (unsigned int)xconn->smb2.credits.seq_range));
607 return false;
610 seq_tmp += xconn->smb2.credits.seq_range;
611 if (seq_id >= seq_tmp) {
612 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
613 "%llu (sequence id %llu) "
614 "(granted = %u, low = %llu, range = %u)\n",
615 (unsigned long long)message_id,
616 (unsigned long long)seq_id,
617 (unsigned int)xconn->smb2.credits.granted,
618 (unsigned long long)xconn->smb2.credits.seq_low,
619 (unsigned int)xconn->smb2.credits.seq_range));
620 return false;
623 offset = seq_id % xconn->smb2.credits.max;
625 if (bitmap_query(credits_bm, offset)) {
626 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
627 "%llu (sequence id %llu) "
628 "(granted = %u, low = %llu, range = %u) "
629 "(bm offset %u)\n",
630 (unsigned long long)message_id,
631 (unsigned long long)seq_id,
632 (unsigned int)xconn->smb2.credits.granted,
633 (unsigned long long)xconn->smb2.credits.seq_low,
634 (unsigned int)xconn->smb2.credits.seq_range,
635 offset));
636 return false;
639 /* Mark the message_ids as seen in the bitmap. */
640 bitmap_set(credits_bm, offset);
642 if (seq_id != xconn->smb2.credits.seq_low) {
643 return true;
647 * Move the window forward by all the message_id's
648 * already seen.
650 while (bitmap_query(credits_bm, offset)) {
651 DEBUG(10,("smb2_validate_sequence_number: clearing "
652 "id %llu (position %u) from bitmap\n",
653 (unsigned long long)(xconn->smb2.credits.seq_low),
654 offset));
655 bitmap_clear(credits_bm, offset);
657 xconn->smb2.credits.seq_low += 1;
658 xconn->smb2.credits.seq_range -= 1;
659 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
662 return true;
665 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
666 const uint8_t *inhdr)
668 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
669 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
670 uint16_t credit_charge = 1;
671 uint64_t i;
673 if (opcode == SMB2_OP_CANCEL) {
674 /* SMB2_CANCEL requests by definition resend messageids. */
675 return true;
678 if (xconn->smb2.credits.multicredit) {
679 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
680 credit_charge = MAX(credit_charge, 1);
683 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
684 "credits_granted %llu, "
685 "seqnum low/range: %llu/%llu\n",
686 (unsigned long long) message_id,
687 (unsigned long long) credit_charge,
688 (unsigned long long) xconn->smb2.credits.granted,
689 (unsigned long long) xconn->smb2.credits.seq_low,
690 (unsigned long long) xconn->smb2.credits.seq_range));
692 if (xconn->smb2.credits.granted < credit_charge) {
693 DEBUG(0, ("smb2_validate_message_id: client used more "
694 "credits than granted, mid %llu, charge %llu, "
695 "credits_granted %llu, "
696 "seqnum low/range: %llu/%llu\n",
697 (unsigned long long) message_id,
698 (unsigned long long) credit_charge,
699 (unsigned long long) xconn->smb2.credits.granted,
700 (unsigned long long) xconn->smb2.credits.seq_low,
701 (unsigned long long) xconn->smb2.credits.seq_range));
702 return false;
706 * now check the message ids
708 * for multi-credit requests we need to check all current mid plus
709 * the implicit mids caused by the credit charge
710 * e.g. current mid = 15, charge 5 => mark 15-19 as used
713 for (i = 0; i <= (credit_charge-1); i++) {
714 uint64_t id = message_id + i;
715 bool ok;
717 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
718 (unsigned long long)message_id,
719 credit_charge,
720 (unsigned long long)id));
722 ok = smb2_validate_sequence_number(xconn, message_id, id);
723 if (!ok) {
724 return false;
728 /* substract used credits */
729 xconn->smb2.credits.granted -= credit_charge;
731 return true;
734 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
736 int count;
737 int idx;
739 count = req->in.vector_count;
741 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
742 /* It's not a SMB2 request */
743 return NT_STATUS_INVALID_PARAMETER;
746 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
747 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
748 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
749 const uint8_t *inhdr = NULL;
751 if (hdr->iov_len != SMB2_HDR_BODY) {
752 return NT_STATUS_INVALID_PARAMETER;
755 if (body->iov_len < 2) {
756 return NT_STATUS_INVALID_PARAMETER;
759 inhdr = (const uint8_t *)hdr->iov_base;
761 /* Check the SMB2 header */
762 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
763 return NT_STATUS_INVALID_PARAMETER;
766 if (!smb2_validate_message_id(req->xconn, inhdr)) {
767 return NT_STATUS_INVALID_PARAMETER;
771 return NT_STATUS_OK;
774 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
775 const struct iovec *in_vector,
776 struct iovec *out_vector)
778 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
779 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
780 uint16_t credit_charge = 1;
781 uint16_t credits_requested;
782 uint32_t out_flags;
783 uint16_t cmd;
784 NTSTATUS out_status;
785 uint16_t credits_granted = 0;
786 uint64_t credits_possible;
787 uint16_t current_max_credits;
790 * first we grant only 1/16th of the max range.
792 * Windows also starts with the 1/16th and then grants
793 * more later. I was only able to trigger higher
794 * values, when using a very high credit charge.
796 * TODO: scale up depending on load, free memory
797 * or other stuff.
798 * Maybe also on the relationship between number
799 * of requests and the used sequence number.
800 * Which means we would grant more credits
801 * for client which use multi credit requests.
803 current_max_credits = xconn->smb2.credits.max / 16;
804 current_max_credits = MAX(current_max_credits, 1);
806 if (xconn->smb2.credits.multicredit) {
807 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
808 credit_charge = MAX(credit_charge, 1);
811 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
812 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
813 credits_requested = MAX(credits_requested, 1);
814 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
815 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
817 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
819 if (xconn->smb2.credits.max < credit_charge) {
820 smbd_server_connection_terminate(xconn,
821 "client error: credit charge > max credits\n");
822 return;
825 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
827 * In case we already send an async interim
828 * response, we should not grant
829 * credits on the final response.
831 credits_granted = 0;
832 } else {
833 uint16_t additional_possible =
834 xconn->smb2.credits.max - credit_charge;
835 uint16_t additional_max = 0;
836 uint16_t additional_credits = credits_requested - 1;
838 switch (cmd) {
839 case SMB2_OP_NEGPROT:
840 break;
841 case SMB2_OP_SESSSETUP:
843 * Windows 2012 RC1 starts to grant
844 * additional credits
845 * with a successful session setup
847 if (NT_STATUS_IS_OK(out_status)) {
848 additional_max = 32;
850 break;
851 default:
853 * We match windows and only grant additional credits
854 * in chunks of 32.
856 additional_max = 32;
857 break;
860 additional_max = MIN(additional_max, additional_possible);
861 additional_credits = MIN(additional_credits, additional_max);
863 credits_granted = credit_charge + additional_credits;
867 * sequence numbers should not wrap
869 * 1. calculate the possible credits until
870 * the sequence numbers start to wrap on 64-bit.
872 * 2. UINT64_MAX is used for Break Notifications.
874 * 2. truncate the possible credits to the maximum
875 * credits we want to grant to the client in total.
877 * 3. remove the range we'll already granted to the client
878 * this makes sure the client consumes the lowest sequence
879 * number, before we can grant additional credits.
881 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
882 if (credits_possible > 0) {
883 /* remove UINT64_MAX */
884 credits_possible -= 1;
886 credits_possible = MIN(credits_possible, current_max_credits);
887 credits_possible -= xconn->smb2.credits.seq_range;
889 credits_granted = MIN(credits_granted, credits_possible);
891 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
892 xconn->smb2.credits.granted += credits_granted;
893 xconn->smb2.credits.seq_range += credits_granted;
895 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
896 "granted %u, current possible/max %u/%u, "
897 "total granted/max/low/range %u/%u/%llu/%u\n",
898 (unsigned int)credits_requested,
899 (unsigned int)credit_charge,
900 (unsigned int)credits_granted,
901 (unsigned int)credits_possible,
902 (unsigned int)current_max_credits,
903 (unsigned int)xconn->smb2.credits.granted,
904 (unsigned int)xconn->smb2.credits.max,
905 (unsigned long long)xconn->smb2.credits.seq_low,
906 (unsigned int)xconn->smb2.credits.seq_range));
909 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
910 struct smbd_smb2_request *outreq)
912 int count, idx;
913 uint16_t total_credits = 0;
915 count = outreq->out.vector_count;
917 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
918 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
919 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
920 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
922 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
924 /* To match Windows, count up what we
925 just granted. */
926 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
927 /* Set to zero in all but the last reply. */
928 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
929 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
930 } else {
931 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
936 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
938 if (req->current_idx <= 1) {
939 if (size <= sizeof(req->out._body)) {
940 return data_blob_const(req->out._body, size);
944 return data_blob_talloc(req, NULL, size);
947 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
949 struct smbXsrv_connection *xconn = req->xconn;
950 TALLOC_CTX *mem_ctx;
951 struct iovec *vector;
952 int count;
953 int idx;
954 bool ok;
956 count = req->in.vector_count;
957 if (count <= ARRAY_SIZE(req->out._vector)) {
958 mem_ctx = req;
959 vector = req->out._vector;
960 } else {
961 vector = talloc_zero_array(req, struct iovec, count);
962 if (vector == NULL) {
963 return NT_STATUS_NO_MEMORY;
965 mem_ctx = vector;
968 vector[0].iov_base = req->out.nbt_hdr;
969 vector[0].iov_len = 4;
970 SIVAL(req->out.nbt_hdr, 0, 0);
972 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
973 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
974 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
975 uint8_t *outhdr = NULL;
976 uint8_t *outbody = NULL;
977 uint32_t next_command_ofs = 0;
978 struct iovec *current = &vector[idx];
980 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
981 /* we have a next command -
982 * setup for the error case. */
983 next_command_ofs = SMB2_HDR_BODY + 9;
986 if (idx == 1) {
987 outhdr = req->out._hdr;
988 } else {
989 outhdr = talloc_zero_array(mem_ctx, uint8_t,
990 OUTVEC_ALLOC_SIZE);
991 if (outhdr == NULL) {
992 return NT_STATUS_NO_MEMORY;
996 outbody = outhdr + SMB2_HDR_BODY;
999 * SMBD_SMB2_TF_IOV_OFS might be used later
1001 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1002 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1004 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1005 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1007 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1008 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1010 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1011 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1013 /* setup the SMB2 header */
1014 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1015 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1016 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1017 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1018 SIVAL(outhdr, SMB2_HDR_STATUS,
1019 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1020 SSVAL(outhdr, SMB2_HDR_OPCODE,
1021 SVAL(inhdr, SMB2_HDR_OPCODE));
1022 SIVAL(outhdr, SMB2_HDR_FLAGS,
1023 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1024 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1025 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1026 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1027 SIVAL(outhdr, SMB2_HDR_PID,
1028 IVAL(inhdr, SMB2_HDR_PID));
1029 SIVAL(outhdr, SMB2_HDR_TID,
1030 IVAL(inhdr, SMB2_HDR_TID));
1031 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1032 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1033 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1034 inhdr + SMB2_HDR_SIGNATURE, 16);
1036 /* setup error body header */
1037 SSVAL(outbody, 0x00, 0x08 + 1);
1038 SSVAL(outbody, 0x02, 0);
1039 SIVAL(outbody, 0x04, 0);
1042 req->out.vector = vector;
1043 req->out.vector_count = count;
1045 /* setup the length of the NBT packet */
1046 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1047 if (!ok) {
1048 return NT_STATUS_INVALID_PARAMETER_MIX;
1051 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1053 return NT_STATUS_OK;
1056 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1057 const char *reason,
1058 const char *location)
1060 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1061 reason, location));
1062 exit_server_cleanly(reason);
1065 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1066 struct iovec *outvec,
1067 const struct iovec *srcvec)
1069 const uint8_t *srctf;
1070 size_t srctf_len;
1071 const uint8_t *srchdr;
1072 size_t srchdr_len;
1073 const uint8_t *srcbody;
1074 size_t srcbody_len;
1075 const uint8_t *expected_srcbody;
1076 const uint8_t *srcdyn;
1077 size_t srcdyn_len;
1078 const uint8_t *expected_srcdyn;
1079 uint8_t *dsttf;
1080 uint8_t *dsthdr;
1081 uint8_t *dstbody;
1082 uint8_t *dstdyn;
1084 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1085 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1086 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1087 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1088 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1089 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1090 expected_srcbody = srchdr + SMB2_HDR_BODY;
1091 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1092 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1093 expected_srcdyn = srcbody + 8;
1095 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1096 return false;
1099 if (srchdr_len != SMB2_HDR_BODY) {
1100 return false;
1103 if (srctf_len == SMB2_TF_HDR_SIZE) {
1104 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1105 if (dsttf == NULL) {
1106 return false;
1108 } else {
1109 dsttf = NULL;
1111 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1112 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1114 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1115 * be allocated with size OUTVEC_ALLOC_SIZE. */
1117 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1118 if (dsthdr == NULL) {
1119 return false;
1121 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1122 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1125 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1126 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1127 * then duplicate this. Else use talloc_memdup().
1130 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1131 dstbody = dsthdr + SMB2_HDR_BODY;
1132 } else {
1133 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1134 if (dstbody == NULL) {
1135 return false;
1138 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1139 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1142 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1143 * pointing to
1144 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1145 * then duplicate this. Else use talloc_memdup().
1148 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1149 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1150 } else if (srcdyn == NULL) {
1151 dstdyn = NULL;
1152 } else {
1153 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1154 if (dstdyn == NULL) {
1155 return false;
1158 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1159 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1161 return true;
1164 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1166 struct smbd_smb2_request *newreq = NULL;
1167 struct iovec *outvec = NULL;
1168 int count = req->out.vector_count;
1169 int i;
1170 bool ok;
1172 newreq = smbd_smb2_request_allocate(req->xconn);
1173 if (!newreq) {
1174 return NULL;
1177 newreq->sconn = req->sconn;
1178 newreq->xconn = req->xconn;
1179 newreq->session = req->session;
1180 newreq->do_encryption = req->do_encryption;
1181 newreq->do_signing = req->do_signing;
1182 newreq->current_idx = req->current_idx;
1184 outvec = talloc_zero_array(newreq, struct iovec, count);
1185 if (!outvec) {
1186 TALLOC_FREE(newreq);
1187 return NULL;
1189 newreq->out.vector = outvec;
1190 newreq->out.vector_count = count;
1192 /* Setup the outvec's identically to req. */
1193 outvec[0].iov_base = newreq->out.nbt_hdr;
1194 outvec[0].iov_len = 4;
1195 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1197 /* Setup the vectors identically to the ones in req. */
1198 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1199 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1200 break;
1204 if (i < count) {
1205 /* Alloc failed. */
1206 TALLOC_FREE(newreq);
1207 return NULL;
1210 ok = smb2_setup_nbt_length(newreq->out.vector,
1211 newreq->out.vector_count);
1212 if (!ok) {
1213 TALLOC_FREE(newreq);
1214 return NULL;
1217 return newreq;
1220 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1222 struct smbXsrv_connection *xconn = req->xconn;
1223 int first_idx = 1;
1224 struct iovec *firsttf = NULL;
1225 struct iovec *outhdr_v = NULL;
1226 uint8_t *outhdr = NULL;
1227 struct smbd_smb2_request *nreq = NULL;
1228 NTSTATUS status;
1229 bool ok;
1231 /* Create a new smb2 request we'll use
1232 for the interim return. */
1233 nreq = dup_smb2_req(req);
1234 if (!nreq) {
1235 return NT_STATUS_NO_MEMORY;
1238 /* Lose the last X out vectors. They're the
1239 ones we'll be using for the async reply. */
1240 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1242 ok = smb2_setup_nbt_length(nreq->out.vector,
1243 nreq->out.vector_count);
1244 if (!ok) {
1245 return NT_STATUS_INVALID_PARAMETER_MIX;
1248 /* Step back to the previous reply. */
1249 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1250 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1251 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1252 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1253 /* And end the chain. */
1254 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1256 /* Calculate outgoing credits */
1257 smb2_calculate_credits(req, nreq);
1259 if (DEBUGLEVEL >= 10) {
1260 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1261 (unsigned int)nreq->current_idx );
1262 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1263 (unsigned int)nreq->out.vector_count );
1264 print_req_vectors(nreq);
1268 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1269 * we need to sign/encrypt here with the last/first key we remembered
1271 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1272 status = smb2_signing_encrypt_pdu(req->first_key,
1273 xconn->smb2.server.cipher,
1274 firsttf,
1275 nreq->out.vector_count - first_idx);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 return status;
1279 } else if (req->last_key.length > 0) {
1280 status = smb2_signing_sign_pdu(req->last_key,
1281 xconn->protocol,
1282 outhdr_v,
1283 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 return status;
1289 nreq->queue_entry.mem_ctx = nreq;
1290 nreq->queue_entry.vector = nreq->out.vector;
1291 nreq->queue_entry.count = nreq->out.vector_count;
1292 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1293 xconn->smb2.send_queue_len++;
1295 status = smbd_smb2_flush_send_queue(xconn);
1296 if (!NT_STATUS_IS_OK(status)) {
1297 return status;
1300 return NT_STATUS_OK;
1303 struct smbd_smb2_request_pending_state {
1304 struct smbd_smb2_send_queue queue_entry;
1305 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1306 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1309 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1310 struct tevent_timer *te,
1311 struct timeval current_time,
1312 void *private_data);
1314 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1315 struct tevent_req *subreq,
1316 uint32_t defer_time)
1318 NTSTATUS status;
1319 struct timeval defer_endtime;
1320 uint8_t *outhdr = NULL;
1321 uint32_t flags;
1323 if (!tevent_req_is_in_progress(subreq)) {
1325 * This is a performance optimization,
1326 * it avoids one tevent_loop iteration,
1327 * which means we avoid one
1328 * talloc_stackframe_pool/talloc_free pair.
1330 tevent_req_notify_callback(subreq);
1331 return NT_STATUS_OK;
1334 req->subreq = subreq;
1335 subreq = NULL;
1337 if (req->async_te) {
1338 /* We're already async. */
1339 return NT_STATUS_OK;
1342 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1343 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1344 if (flags & SMB2_HDR_FLAG_ASYNC) {
1345 /* We're already async. */
1346 return NT_STATUS_OK;
1349 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1351 * We're trying to go async in a compound request
1352 * chain. This is only allowed for opens that cause an
1353 * oplock break or for the last operation in the
1354 * chain, otherwise it is not allowed. See
1355 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1357 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1359 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1361 * Cancel the outstanding request.
1363 bool ok = tevent_req_cancel(req->subreq);
1364 if (ok) {
1365 return NT_STATUS_OK;
1367 TALLOC_FREE(req->subreq);
1368 return smbd_smb2_request_error(req,
1369 NT_STATUS_INTERNAL_ERROR);
1373 if (DEBUGLEVEL >= 10) {
1374 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1375 (unsigned int)req->current_idx );
1376 print_req_vectors(req);
1379 if (req->current_idx > 1) {
1381 * We're going async in a compound
1382 * chain after the first request has
1383 * already been processed. Send an
1384 * interim response containing the
1385 * set of replies already generated.
1387 int idx = req->current_idx;
1389 status = smb2_send_async_interim_response(req);
1390 if (!NT_STATUS_IS_OK(status)) {
1391 return status;
1393 if (req->first_key.length > 0) {
1394 data_blob_clear_free(&req->first_key);
1397 req->current_idx = 1;
1400 * Re-arrange the in.vectors to remove what
1401 * we just sent.
1403 memmove(&req->in.vector[1],
1404 &req->in.vector[idx],
1405 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1406 req->in.vector_count = 1 + (req->in.vector_count - idx);
1408 /* Re-arrange the out.vectors to match. */
1409 memmove(&req->out.vector[1],
1410 &req->out.vector[idx],
1411 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1412 req->out.vector_count = 1 + (req->out.vector_count - idx);
1414 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1416 * We only have one remaining request as
1417 * we've processed everything else.
1418 * This is no longer a compound request.
1420 req->compound_related = false;
1421 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1422 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1423 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1426 if (req->last_key.length > 0) {
1427 data_blob_clear_free(&req->last_key);
1430 defer_endtime = timeval_current_ofs_usec(defer_time);
1431 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1432 req, defer_endtime,
1433 smbd_smb2_request_pending_timer,
1434 req);
1435 if (req->async_te == NULL) {
1436 return NT_STATUS_NO_MEMORY;
1439 return NT_STATUS_OK;
1442 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1443 struct smbXsrv_connection *xconn)
1445 struct smbXsrv_channel_global0 *c = NULL;
1446 NTSTATUS status;
1447 DATA_BLOB key = data_blob_null;
1449 status = smbXsrv_session_find_channel(session, xconn, &c);
1450 if (NT_STATUS_IS_OK(status)) {
1451 key = c->signing_key;
1454 if (key.length == 0) {
1455 key = session->global->signing_key;
1458 return key;
1461 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1462 struct tevent_timer *te,
1463 struct timeval current_time,
1464 void *private_data)
1466 struct smbd_smb2_request *req =
1467 talloc_get_type_abort(private_data,
1468 struct smbd_smb2_request);
1469 struct smbXsrv_connection *xconn = req->xconn;
1470 struct smbd_smb2_request_pending_state *state = NULL;
1471 uint8_t *outhdr = NULL;
1472 const uint8_t *inhdr = NULL;
1473 uint8_t *tf = NULL;
1474 size_t tf_len = 0;
1475 uint8_t *hdr = NULL;
1476 uint8_t *body = NULL;
1477 uint8_t *dyn = NULL;
1478 uint32_t flags = 0;
1479 uint64_t session_id = 0;
1480 uint64_t message_id = 0;
1481 uint64_t nonce_high = 0;
1482 uint64_t nonce_low = 0;
1483 uint64_t async_id = 0;
1484 NTSTATUS status;
1485 bool ok;
1487 TALLOC_FREE(req->async_te);
1489 /* Ensure our final reply matches the interim one. */
1490 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1491 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1492 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1493 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1494 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1496 async_id = message_id; /* keep it simple for now... */
1498 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1499 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1501 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1502 "going async\n",
1503 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1504 (unsigned long long)async_id ));
1507 * What we send is identical to a smbd_smb2_request_error
1508 * packet with an error status of STATUS_PENDING. Make use
1509 * of this fact sometime when refactoring. JRA.
1512 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1513 if (state == NULL) {
1514 smbd_server_connection_terminate(xconn,
1515 nt_errstr(NT_STATUS_NO_MEMORY));
1516 return;
1519 tf = state->buf + NBT_HDR_SIZE;
1520 tf_len = SMB2_TF_HDR_SIZE;
1522 hdr = tf + SMB2_TF_HDR_SIZE;
1523 body = hdr + SMB2_HDR_BODY;
1524 dyn = body + 8;
1526 if (req->do_encryption) {
1527 struct smbXsrv_session *x = req->session;
1529 nonce_high = x->nonce_high;
1530 nonce_low = x->nonce_low;
1532 x->nonce_low += 1;
1533 if (x->nonce_low == 0) {
1534 x->nonce_low += 1;
1535 x->nonce_high += 1;
1539 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1540 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1541 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1542 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1544 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1545 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1546 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1547 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1548 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1550 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1551 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1552 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1553 SBVAL(hdr, SMB2_HDR_PID, async_id);
1554 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1555 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1556 memcpy(hdr+SMB2_HDR_SIGNATURE,
1557 outhdr+SMB2_HDR_SIGNATURE, 16);
1559 SSVAL(body, 0x00, 0x08 + 1);
1561 SCVAL(body, 0x02, 0);
1562 SCVAL(body, 0x03, 0);
1563 SIVAL(body, 0x04, 0);
1564 /* Match W2K8R2... */
1565 SCVAL(dyn, 0x00, 0x21);
1567 state->vector[0].iov_base = (void *)state->buf;
1568 state->vector[0].iov_len = NBT_HDR_SIZE;
1570 if (req->do_encryption) {
1571 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1572 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1573 } else {
1574 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1575 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1578 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1579 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1581 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1582 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1584 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1585 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1587 ok = smb2_setup_nbt_length(state->vector,
1588 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1589 if (!ok) {
1590 smbd_server_connection_terminate(
1591 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1592 return;
1595 /* Ensure we correctly go through crediting. Grant
1596 the credits now, and zero credits on the final
1597 response. */
1598 smb2_set_operation_credit(req->xconn,
1599 SMBD_SMB2_IN_HDR_IOV(req),
1600 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1602 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1604 if (DEBUGLVL(10)) {
1605 int i;
1607 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1608 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1609 (unsigned int)i,
1610 (unsigned int)ARRAY_SIZE(state->vector),
1611 (unsigned int)state->vector[i].iov_len);
1615 if (req->do_encryption) {
1616 struct smbXsrv_session *x = req->session;
1617 DATA_BLOB encryption_key = x->global->encryption_key;
1619 status = smb2_signing_encrypt_pdu(encryption_key,
1620 xconn->smb2.server.cipher,
1621 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1622 SMBD_SMB2_NUM_IOV_PER_REQ);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 smbd_server_connection_terminate(xconn,
1625 nt_errstr(status));
1626 return;
1628 } else if (req->do_signing) {
1629 struct smbXsrv_session *x = req->session;
1630 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1632 status = smb2_signing_sign_pdu(signing_key,
1633 xconn->protocol,
1634 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1635 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 smbd_server_connection_terminate(xconn,
1638 nt_errstr(status));
1639 return;
1643 state->queue_entry.mem_ctx = state;
1644 state->queue_entry.vector = state->vector;
1645 state->queue_entry.count = ARRAY_SIZE(state->vector);
1646 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1647 xconn->smb2.send_queue_len++;
1649 status = smbd_smb2_flush_send_queue(xconn);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 smbd_server_connection_terminate(xconn,
1652 nt_errstr(status));
1653 return;
1657 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1659 struct smbXsrv_connection *xconn = req->xconn;
1660 struct smbd_smb2_request *cur;
1661 const uint8_t *inhdr;
1662 uint32_t flags;
1663 uint64_t search_message_id;
1664 uint64_t search_async_id;
1665 uint64_t found_id;
1667 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1669 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1670 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1671 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1674 * we don't need the request anymore
1675 * cancel requests never have a response
1677 DLIST_REMOVE(xconn->smb2.requests, req);
1678 TALLOC_FREE(req);
1680 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1681 const uint8_t *outhdr;
1682 uint64_t message_id;
1683 uint64_t async_id;
1685 if (cur->compound_related) {
1687 * Never cancel anything in a compound request.
1688 * Way too hard to deal with the result.
1690 continue;
1693 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1695 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1696 async_id = BVAL(outhdr, SMB2_HDR_PID);
1698 if (flags & SMB2_HDR_FLAG_ASYNC) {
1699 if (search_async_id == async_id) {
1700 found_id = async_id;
1701 break;
1703 } else {
1704 if (search_message_id == message_id) {
1705 found_id = message_id;
1706 break;
1711 if (cur && cur->subreq) {
1712 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1713 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1714 "cancel opcode[%s] mid %llu\n",
1715 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1716 (unsigned long long)found_id ));
1717 tevent_req_cancel(cur->subreq);
1720 return NT_STATUS_OK;
1723 /*************************************************************
1724 Ensure an incoming tid is a valid one for us to access.
1725 Change to the associated uid credentials and chdir to the
1726 valid tid directory.
1727 *************************************************************/
1729 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1731 const uint8_t *inhdr;
1732 uint32_t in_flags;
1733 uint32_t in_tid;
1734 struct smbXsrv_tcon *tcon;
1735 NTSTATUS status;
1736 NTTIME now = timeval_to_nttime(&req->request_time);
1738 req->tcon = NULL;
1740 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1742 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1743 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1745 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1746 in_tid = req->last_tid;
1749 req->last_tid = 0;
1751 status = smb2srv_tcon_lookup(req->session,
1752 in_tid, now, &tcon);
1753 if (!NT_STATUS_IS_OK(status)) {
1754 return status;
1757 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1758 return NT_STATUS_ACCESS_DENIED;
1761 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1762 if (!set_current_service(tcon->compat, 0, true)) {
1763 return NT_STATUS_ACCESS_DENIED;
1766 req->tcon = tcon;
1767 req->last_tid = in_tid;
1769 return NT_STATUS_OK;
1772 /*************************************************************
1773 Ensure an incoming session_id is a valid one for us to access.
1774 *************************************************************/
1776 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1778 const uint8_t *inhdr;
1779 uint32_t in_flags;
1780 uint16_t in_opcode;
1781 uint64_t in_session_id;
1782 struct smbXsrv_session *session = NULL;
1783 struct auth_session_info *session_info;
1784 NTSTATUS status;
1785 NTTIME now = timeval_to_nttime(&req->request_time);
1787 req->session = NULL;
1788 req->tcon = NULL;
1790 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1792 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1793 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1794 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1796 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1797 in_session_id = req->last_session_id;
1800 req->last_session_id = 0;
1802 /* lookup an existing session */
1803 status = smb2srv_session_lookup(req->xconn,
1804 in_session_id, now,
1805 &session);
1806 if (session) {
1807 req->session = session;
1808 req->last_session_id = in_session_id;
1810 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1811 switch (in_opcode) {
1812 case SMB2_OP_SESSSETUP:
1813 status = NT_STATUS_OK;
1814 break;
1815 default:
1816 break;
1819 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1820 switch (in_opcode) {
1821 case SMB2_OP_TCON:
1822 case SMB2_OP_CREATE:
1823 case SMB2_OP_GETINFO:
1824 case SMB2_OP_SETINFO:
1825 return NT_STATUS_INVALID_HANDLE;
1826 default:
1828 * Notice the check for
1829 * (session_info == NULL)
1830 * below.
1832 status = NT_STATUS_OK;
1833 break;
1836 if (!NT_STATUS_IS_OK(status)) {
1837 return status;
1840 session_info = session->global->auth_session_info;
1841 if (session_info == NULL) {
1842 return NT_STATUS_INVALID_HANDLE;
1845 if (in_session_id != req->xconn->client->last_session_id) {
1846 req->xconn->client->last_session_id = in_session_id;
1847 set_current_user_info(session_info->unix_info->sanitized_username,
1848 session_info->unix_info->unix_name,
1849 session_info->info->domain_name);
1852 return NT_STATUS_OK;
1855 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1856 uint32_t data_length)
1858 struct smbXsrv_connection *xconn = req->xconn;
1859 uint16_t needed_charge;
1860 uint16_t credit_charge = 1;
1861 const uint8_t *inhdr;
1863 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1865 if (xconn->smb2.credits.multicredit) {
1866 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1867 credit_charge = MAX(credit_charge, 1);
1870 needed_charge = (data_length - 1)/ 65536 + 1;
1872 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1873 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1874 credit_charge, needed_charge));
1876 if (needed_charge > credit_charge) {
1877 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1878 credit_charge, needed_charge));
1879 return NT_STATUS_INVALID_PARAMETER;
1882 return NT_STATUS_OK;
1885 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1886 size_t expected_body_size)
1888 struct iovec *inhdr_v;
1889 const uint8_t *inhdr;
1890 uint16_t opcode;
1891 const uint8_t *inbody;
1892 size_t body_size;
1893 size_t min_dyn_size = expected_body_size & 0x00000001;
1894 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1897 * The following should be checked already.
1899 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1900 return NT_STATUS_INTERNAL_ERROR;
1902 if (req->current_idx > max_idx) {
1903 return NT_STATUS_INTERNAL_ERROR;
1906 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1907 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1908 return NT_STATUS_INTERNAL_ERROR;
1910 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1911 return NT_STATUS_INTERNAL_ERROR;
1914 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1915 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1917 switch (opcode) {
1918 case SMB2_OP_IOCTL:
1919 case SMB2_OP_GETINFO:
1920 min_dyn_size = 0;
1921 break;
1922 case SMB2_OP_WRITE:
1923 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1924 if (req->smb1req->unread_bytes < min_dyn_size) {
1925 return NT_STATUS_INVALID_PARAMETER;
1928 min_dyn_size = 0;
1930 break;
1934 * Now check the expected body size,
1935 * where the last byte might be in the
1936 * dynamic section..
1938 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1939 return NT_STATUS_INVALID_PARAMETER;
1941 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1942 return NT_STATUS_INVALID_PARAMETER;
1945 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1947 body_size = SVAL(inbody, 0x00);
1948 if (body_size != expected_body_size) {
1949 return NT_STATUS_INVALID_PARAMETER;
1952 return NT_STATUS_OK;
1955 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1957 struct smbXsrv_connection *xconn = req->xconn;
1958 const struct smbd_smb2_dispatch_table *call = NULL;
1959 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1960 const uint8_t *inhdr;
1961 uint16_t opcode;
1962 uint32_t flags;
1963 uint64_t mid;
1964 NTSTATUS status;
1965 NTSTATUS session_status;
1966 uint32_t allowed_flags;
1967 NTSTATUS return_value;
1968 struct smbXsrv_session *x = NULL;
1969 bool signing_required = false;
1970 bool encryption_required = false;
1972 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1974 DO_PROFILE_INC(request);
1976 /* TODO: verify more things */
1978 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1979 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1980 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1981 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1982 smb2_opcode_name(opcode),
1983 (unsigned long long)mid));
1985 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1987 * once the protocol is negotiated
1988 * SMB2_OP_NEGPROT is not allowed anymore
1990 if (opcode == SMB2_OP_NEGPROT) {
1991 /* drop the connection */
1992 return NT_STATUS_INVALID_PARAMETER;
1994 } else {
1996 * if the protocol is not negotiated yet
1997 * only SMB2_OP_NEGPROT is allowed.
1999 if (opcode != SMB2_OP_NEGPROT) {
2000 /* drop the connection */
2001 return NT_STATUS_INVALID_PARAMETER;
2006 * Check if the client provided a valid session id,
2007 * if so smbd_smb2_request_check_session() calls
2008 * set_current_user_info().
2010 * As some command don't require a valid session id
2011 * we defer the check of the session_status
2013 session_status = smbd_smb2_request_check_session(req);
2014 x = req->session;
2015 if (x != NULL) {
2016 signing_required = x->global->signing_required;
2017 encryption_required = x->global->encryption_required;
2020 req->do_signing = false;
2021 req->do_encryption = false;
2022 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2023 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2024 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2026 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2027 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2028 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2029 (unsigned long long)x->global->session_wire_id,
2030 (unsigned long long)tf_session_id));
2032 * TODO: windows allows this...
2033 * should we drop the connection?
2035 * For now we just return ACCESS_DENIED
2036 * (Windows clients never trigger this)
2037 * and wait for an update of [MS-SMB2].
2039 return smbd_smb2_request_error(req,
2040 NT_STATUS_ACCESS_DENIED);
2043 req->do_encryption = true;
2046 if (encryption_required && !req->do_encryption) {
2047 return smbd_smb2_request_error(req,
2048 NT_STATUS_ACCESS_DENIED);
2051 call = smbd_smb2_call(opcode);
2052 if (call == NULL) {
2053 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2056 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2057 SMB2_HDR_FLAG_SIGNED |
2058 SMB2_HDR_FLAG_DFS;
2059 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2060 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2062 if (opcode == SMB2_OP_NEGPROT) {
2063 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2064 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2067 if (opcode == SMB2_OP_CANCEL) {
2068 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2070 if ((flags & ~allowed_flags) != 0) {
2071 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2074 if (flags & SMB2_HDR_FLAG_CHAINED) {
2076 * This check is mostly for giving the correct error code
2077 * for compounded requests.
2079 if (!NT_STATUS_IS_OK(session_status)) {
2080 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2082 } else {
2083 req->compat_chain_fsp = NULL;
2086 if (req->do_encryption) {
2087 signing_required = false;
2088 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2089 DATA_BLOB signing_key = data_blob_null;
2091 if (x == NULL) {
2093 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2094 * If the SMB2 header of the SMB2 NEGOTIATE
2095 * request has the SMB2_FLAGS_SIGNED bit set in the
2096 * Flags field, the server MUST fail the request
2097 * with STATUS_INVALID_PARAMETER.
2099 * Microsoft test tool checks this.
2102 if ((opcode == SMB2_OP_NEGPROT) &&
2103 (flags & SMB2_HDR_FLAG_SIGNED)) {
2104 status = NT_STATUS_INVALID_PARAMETER;
2105 } else {
2106 status = NT_STATUS_USER_SESSION_DELETED;
2108 return smbd_smb2_request_error(req, status);
2111 signing_key = smbd_smb2_signing_key(x, xconn);
2114 * If we have a signing key, we should
2115 * sign the response
2117 if (signing_key.length > 0) {
2118 req->do_signing = true;
2121 status = smb2_signing_check_pdu(signing_key,
2122 xconn->protocol,
2123 SMBD_SMB2_IN_HDR_IOV(req),
2124 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 return smbd_smb2_request_error(req, status);
2130 * Now that we know the request was correctly signed
2131 * we have to sign the response too.
2133 req->do_signing = true;
2135 if (!NT_STATUS_IS_OK(session_status)) {
2136 return smbd_smb2_request_error(req, session_status);
2138 } else if (opcode == SMB2_OP_CANCEL) {
2139 /* Cancel requests are allowed to skip the signing */
2140 } else if (signing_required) {
2142 * If signing is required we try to sign
2143 * a possible error response
2145 req->do_signing = true;
2146 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2149 if (flags & SMB2_HDR_FLAG_CHAINED) {
2150 req->compound_related = true;
2153 if (call->need_session) {
2154 if (!NT_STATUS_IS_OK(session_status)) {
2155 return smbd_smb2_request_error(req, session_status);
2159 if (call->need_tcon) {
2160 SMB_ASSERT(call->need_session);
2163 * This call needs to be run as user.
2165 * smbd_smb2_request_check_tcon()
2166 * calls change_to_user() on success.
2168 status = smbd_smb2_request_check_tcon(req);
2169 if (!NT_STATUS_IS_OK(status)) {
2170 return smbd_smb2_request_error(req, status);
2172 if (req->tcon->global->encryption_required) {
2173 encryption_required = true;
2175 if (encryption_required && !req->do_encryption) {
2176 return smbd_smb2_request_error(req,
2177 NT_STATUS_ACCESS_DENIED);
2181 if (call->fileid_ofs != 0) {
2182 size_t needed = call->fileid_ofs + 16;
2183 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2184 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2185 uint64_t file_id_persistent;
2186 uint64_t file_id_volatile;
2187 struct files_struct *fsp;
2189 SMB_ASSERT(call->need_tcon);
2191 if (needed > body_size) {
2192 return smbd_smb2_request_error(req,
2193 NT_STATUS_INVALID_PARAMETER);
2196 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2197 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2199 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2200 if (fsp == NULL) {
2201 if (!call->allow_invalid_fileid) {
2202 return smbd_smb2_request_error(req,
2203 NT_STATUS_FILE_CLOSED);
2206 if (file_id_persistent != UINT64_MAX) {
2207 return smbd_smb2_request_error(req,
2208 NT_STATUS_FILE_CLOSED);
2210 if (file_id_volatile != UINT64_MAX) {
2211 return smbd_smb2_request_error(req,
2212 NT_STATUS_FILE_CLOSED);
2217 if (call->as_root) {
2218 SMB_ASSERT(call->fileid_ofs == 0);
2219 /* This call needs to be run as root */
2220 change_to_root_user();
2221 } else {
2222 SMB_ASSERT(call->need_tcon);
2225 #define _INBYTES(_r) \
2226 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2228 switch (opcode) {
2229 case SMB2_OP_NEGPROT:
2230 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2231 req->profile, _INBYTES(req));
2232 return_value = smbd_smb2_request_process_negprot(req);
2233 break;
2235 case SMB2_OP_SESSSETUP:
2236 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2237 req->profile, _INBYTES(req));
2238 return_value = smbd_smb2_request_process_sesssetup(req);
2239 break;
2241 case SMB2_OP_LOGOFF:
2242 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2243 req->profile, _INBYTES(req));
2244 return_value = smbd_smb2_request_process_logoff(req);
2245 break;
2247 case SMB2_OP_TCON:
2248 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2249 req->profile, _INBYTES(req));
2250 return_value = smbd_smb2_request_process_tcon(req);
2251 break;
2253 case SMB2_OP_TDIS:
2254 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2255 req->profile, _INBYTES(req));
2256 return_value = smbd_smb2_request_process_tdis(req);
2257 break;
2259 case SMB2_OP_CREATE:
2260 if (req->subreq == NULL) {
2261 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2262 req->profile, _INBYTES(req));
2263 } else {
2264 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2266 return_value = smbd_smb2_request_process_create(req);
2267 break;
2269 case SMB2_OP_CLOSE:
2270 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2271 req->profile, _INBYTES(req));
2272 return_value = smbd_smb2_request_process_close(req);
2273 break;
2275 case SMB2_OP_FLUSH:
2276 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2277 req->profile, _INBYTES(req));
2278 return_value = smbd_smb2_request_process_flush(req);
2279 break;
2281 case SMB2_OP_READ:
2282 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2283 req->profile, _INBYTES(req));
2284 return_value = smbd_smb2_request_process_read(req);
2285 break;
2287 case SMB2_OP_WRITE:
2288 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2289 req->profile, _INBYTES(req));
2290 return_value = smbd_smb2_request_process_write(req);
2291 break;
2293 case SMB2_OP_LOCK:
2294 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2295 req->profile, _INBYTES(req));
2296 return_value = smbd_smb2_request_process_lock(req);
2297 break;
2299 case SMB2_OP_IOCTL:
2300 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2301 req->profile, _INBYTES(req));
2302 return_value = smbd_smb2_request_process_ioctl(req);
2303 break;
2305 case SMB2_OP_CANCEL:
2306 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2307 req->profile, _INBYTES(req));
2308 return_value = smbd_smb2_request_process_cancel(req);
2309 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2310 break;
2312 case SMB2_OP_KEEPALIVE:
2313 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2314 req->profile, _INBYTES(req));
2315 return_value = smbd_smb2_request_process_keepalive(req);
2316 break;
2318 case SMB2_OP_QUERY_DIRECTORY:
2319 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2320 req->profile, _INBYTES(req));
2321 return_value = smbd_smb2_request_process_query_directory(req);
2322 break;
2324 case SMB2_OP_NOTIFY:
2325 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2326 req->profile, _INBYTES(req));
2327 return_value = smbd_smb2_request_process_notify(req);
2328 break;
2330 case SMB2_OP_GETINFO:
2331 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2332 req->profile, _INBYTES(req));
2333 return_value = smbd_smb2_request_process_getinfo(req);
2334 break;
2336 case SMB2_OP_SETINFO:
2337 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2338 req->profile, _INBYTES(req));
2339 return_value = smbd_smb2_request_process_setinfo(req);
2340 break;
2342 case SMB2_OP_BREAK:
2343 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2344 req->profile, _INBYTES(req));
2345 return_value = smbd_smb2_request_process_break(req);
2346 break;
2348 default:
2349 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2350 break;
2352 return return_value;
2355 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2357 struct smbXsrv_connection *xconn = req->xconn;
2358 int first_idx = 1;
2359 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2360 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2361 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2362 NTSTATUS status;
2363 bool ok;
2365 req->subreq = NULL;
2366 TALLOC_FREE(req->async_te);
2368 if (req->do_encryption &&
2369 (firsttf->iov_len == 0) &&
2370 (req->first_key.length == 0) &&
2371 (req->session != NULL) &&
2372 (req->session->global->encryption_key.length != 0))
2374 DATA_BLOB encryption_key = req->session->global->encryption_key;
2375 uint8_t *tf;
2376 uint64_t session_id = req->session->global->session_wire_id;
2377 struct smbXsrv_session *x = req->session;
2378 uint64_t nonce_high;
2379 uint64_t nonce_low;
2381 nonce_high = x->nonce_high;
2382 nonce_low = x->nonce_low;
2384 x->nonce_low += 1;
2385 if (x->nonce_low == 0) {
2386 x->nonce_low += 1;
2387 x->nonce_high += 1;
2391 * We need to place the SMB2_TRANSFORM header before the
2392 * first SMB2 header
2396 * we need to remember the encryption key
2397 * and defer the signing/encryption until
2398 * we are sure that we do not change
2399 * the header again.
2401 req->first_key = data_blob_dup_talloc(req, encryption_key);
2402 if (req->first_key.data == NULL) {
2403 return NT_STATUS_NO_MEMORY;
2406 tf = talloc_zero_array(req, uint8_t,
2407 SMB2_TF_HDR_SIZE);
2408 if (tf == NULL) {
2409 return NT_STATUS_NO_MEMORY;
2412 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2413 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2414 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2415 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2417 firsttf->iov_base = (void *)tf;
2418 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2421 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2422 (req->last_key.length > 0) &&
2423 (firsttf->iov_len == 0))
2425 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2426 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2429 * As we are sure the header of the last request in the
2430 * compound chain will not change, we can to sign here
2431 * with the last signing key we remembered.
2433 status = smb2_signing_sign_pdu(req->last_key,
2434 xconn->protocol,
2435 lasthdr,
2436 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 return status;
2441 if (req->last_key.length > 0) {
2442 data_blob_clear_free(&req->last_key);
2445 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2446 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2448 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2450 if (req->current_idx < req->out.vector_count) {
2452 * We must process the remaining compound
2453 * SMB2 requests before any new incoming SMB2
2454 * requests. This is because incoming SMB2
2455 * requests may include a cancel for a
2456 * compound request we haven't processed
2457 * yet.
2459 struct tevent_immediate *im = tevent_create_immediate(req);
2460 if (!im) {
2461 return NT_STATUS_NO_MEMORY;
2464 if (req->do_signing && firsttf->iov_len == 0) {
2465 struct smbXsrv_session *x = req->session;
2466 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2469 * we need to remember the signing key
2470 * and defer the signing until
2471 * we are sure that we do not change
2472 * the header again.
2474 req->last_key = data_blob_dup_talloc(req, signing_key);
2475 if (req->last_key.data == NULL) {
2476 return NT_STATUS_NO_MEMORY;
2480 tevent_schedule_immediate(im,
2481 req->sconn->ev_ctx,
2482 smbd_smb2_request_dispatch_immediate,
2483 req);
2484 return NT_STATUS_OK;
2487 if (req->compound_related) {
2488 req->compound_related = false;
2491 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2492 if (!ok) {
2493 return NT_STATUS_INVALID_PARAMETER_MIX;
2496 /* Set credit for these operations (zero credits if this
2497 is a final reply for an async operation). */
2498 smb2_calculate_credits(req, req);
2501 * now check if we need to sign the current response
2503 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2504 status = smb2_signing_encrypt_pdu(req->first_key,
2505 xconn->smb2.server.cipher,
2506 firsttf,
2507 req->out.vector_count - first_idx);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 return status;
2511 } else if (req->do_signing) {
2512 struct smbXsrv_session *x = req->session;
2513 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2515 status = smb2_signing_sign_pdu(signing_key,
2516 xconn->protocol,
2517 outhdr,
2518 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 return status;
2523 if (req->first_key.length > 0) {
2524 data_blob_clear_free(&req->first_key);
2527 if (req->preauth != NULL) {
2528 struct hc_sha512state sctx;
2529 int i;
2531 samba_SHA512_Init(&sctx);
2532 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2533 sizeof(req->preauth->sha512_value));
2534 for (i = 1; i < req->in.vector_count; i++) {
2535 samba_SHA512_Update(&sctx,
2536 req->in.vector[i].iov_base,
2537 req->in.vector[i].iov_len);
2539 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2541 samba_SHA512_Init(&sctx);
2542 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2543 sizeof(req->preauth->sha512_value));
2544 for (i = 1; i < req->out.vector_count; i++) {
2545 samba_SHA512_Update(&sctx,
2546 req->out.vector[i].iov_base,
2547 req->out.vector[i].iov_len);
2549 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2551 req->preauth = NULL;
2554 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2555 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2556 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2557 /* Dynamic part is NULL. Chop it off,
2558 We're going to send it via sendfile. */
2559 req->out.vector_count -= 1;
2563 * We're done with this request -
2564 * move it off the "being processed" queue.
2566 DLIST_REMOVE(xconn->smb2.requests, req);
2568 req->queue_entry.mem_ctx = req;
2569 req->queue_entry.vector = req->out.vector;
2570 req->queue_entry.count = req->out.vector_count;
2571 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2572 xconn->smb2.send_queue_len++;
2574 status = smbd_smb2_flush_send_queue(xconn);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 return status;
2579 return NT_STATUS_OK;
2582 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2584 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2585 struct tevent_immediate *im,
2586 void *private_data)
2588 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2589 struct smbd_smb2_request);
2590 struct smbXsrv_connection *xconn = req->xconn;
2591 NTSTATUS status;
2593 TALLOC_FREE(im);
2595 if (DEBUGLEVEL >= 10) {
2596 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2597 req->current_idx, req->in.vector_count));
2598 print_req_vectors(req);
2601 status = smbd_smb2_request_dispatch(req);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 smbd_server_connection_terminate(xconn, nt_errstr(status));
2604 return;
2607 status = smbd_smb2_request_next_incoming(xconn);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 smbd_server_connection_terminate(xconn, nt_errstr(status));
2610 return;
2614 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2615 NTSTATUS status,
2616 DATA_BLOB body, DATA_BLOB *dyn,
2617 const char *location)
2619 uint8_t *outhdr;
2620 struct iovec *outbody_v;
2621 struct iovec *outdyn_v;
2622 uint32_t next_command_ofs;
2624 DEBUG(10,("smbd_smb2_request_done_ex: "
2625 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2626 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2627 dyn ? "yes": "no",
2628 (unsigned int)(dyn ? dyn->length : 0),
2629 location));
2631 if (body.length < 2) {
2632 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2635 if ((body.length % 2) != 0) {
2636 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2639 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2640 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2641 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2643 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2644 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2646 outbody_v->iov_base = (void *)body.data;
2647 outbody_v->iov_len = body.length;
2649 if (dyn) {
2650 outdyn_v->iov_base = (void *)dyn->data;
2651 outdyn_v->iov_len = dyn->length;
2652 } else {
2653 outdyn_v->iov_base = NULL;
2654 outdyn_v->iov_len = 0;
2657 /* see if we need to recalculate the offset to the next response */
2658 if (next_command_ofs > 0) {
2659 next_command_ofs = SMB2_HDR_BODY;
2660 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2661 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2664 if ((next_command_ofs % 8) != 0) {
2665 size_t pad_size = 8 - (next_command_ofs % 8);
2666 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2668 * if the dyn buffer is empty
2669 * we can use it to add padding
2671 uint8_t *pad;
2673 pad = talloc_zero_array(req,
2674 uint8_t, pad_size);
2675 if (pad == NULL) {
2676 return smbd_smb2_request_error(req,
2677 NT_STATUS_NO_MEMORY);
2680 outdyn_v->iov_base = (void *)pad;
2681 outdyn_v->iov_len = pad_size;
2682 } else {
2684 * For now we copy the dynamic buffer
2685 * and add the padding to the new buffer
2687 size_t old_size;
2688 uint8_t *old_dyn;
2689 size_t new_size;
2690 uint8_t *new_dyn;
2692 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2693 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2695 new_size = old_size + pad_size;
2696 new_dyn = talloc_zero_array(req,
2697 uint8_t, new_size);
2698 if (new_dyn == NULL) {
2699 return smbd_smb2_request_error(req,
2700 NT_STATUS_NO_MEMORY);
2703 memcpy(new_dyn, old_dyn, old_size);
2704 memset(new_dyn + old_size, 0, pad_size);
2706 outdyn_v->iov_base = (void *)new_dyn;
2707 outdyn_v->iov_len = new_size;
2709 next_command_ofs += pad_size;
2712 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2714 return smbd_smb2_request_reply(req);
2717 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2718 NTSTATUS status,
2719 DATA_BLOB *info,
2720 const char *location)
2722 struct smbXsrv_connection *xconn = req->xconn;
2723 DATA_BLOB body;
2724 DATA_BLOB _dyn;
2725 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2726 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2728 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2729 req->current_idx, nt_errstr(status), info ? " +info" : "",
2730 location));
2732 if (unread_bytes) {
2733 /* Recvfile error. Drain incoming socket. */
2734 size_t ret;
2736 errno = 0;
2737 ret = drain_socket(xconn->transport.sock, unread_bytes);
2738 if (ret != unread_bytes) {
2739 NTSTATUS error;
2741 if (errno == 0) {
2742 error = NT_STATUS_IO_DEVICE_ERROR;
2743 } else {
2744 error = map_nt_error_from_unix_common(errno);
2747 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2748 "ret[%u] errno[%d] => %s\n",
2749 (unsigned)unread_bytes,
2750 (unsigned)ret, errno, nt_errstr(error)));
2751 return error;
2755 body.data = outhdr + SMB2_HDR_BODY;
2756 body.length = 8;
2757 SSVAL(body.data, 0, 9);
2759 if (info) {
2760 SIVAL(body.data, 0x04, info->length);
2761 } else {
2762 /* Allocated size of req->out.vector[i].iov_base
2763 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2764 * 1 byte without having to do an alloc.
2766 info = &_dyn;
2767 info->data = ((uint8_t *)outhdr) +
2768 OUTVEC_ALLOC_SIZE - 1;
2769 info->length = 1;
2770 SCVAL(info->data, 0, 0);
2774 * Note: Even if there is an error, continue to process the request.
2775 * per MS-SMB2.
2778 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2782 struct smbd_smb2_send_break_state {
2783 struct smbd_smb2_send_queue queue_entry;
2784 uint8_t nbt_hdr[NBT_HDR_SIZE];
2785 uint8_t tf[SMB2_TF_HDR_SIZE];
2786 uint8_t hdr[SMB2_HDR_BODY];
2787 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2788 uint8_t body[1];
2791 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2792 struct smbXsrv_session *session,
2793 struct smbXsrv_tcon *tcon,
2794 const uint8_t *body,
2795 size_t body_len)
2797 struct smbd_smb2_send_break_state *state;
2798 bool do_encryption = false;
2799 uint64_t session_wire_id = 0;
2800 uint64_t nonce_high = 0;
2801 uint64_t nonce_low = 0;
2802 NTSTATUS status;
2803 size_t statelen;
2804 bool ok;
2806 if (session != NULL) {
2807 session_wire_id = session->global->session_wire_id;
2808 do_encryption = session->global->encryption_required;
2809 if (tcon->global->encryption_required) {
2810 do_encryption = true;
2814 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2815 body_len;
2817 state = talloc_zero_size(xconn, statelen);
2818 if (state == NULL) {
2819 return NT_STATUS_NO_MEMORY;
2821 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2823 if (do_encryption) {
2824 nonce_high = session->nonce_high;
2825 nonce_low = session->nonce_low;
2827 session->nonce_low += 1;
2828 if (session->nonce_low == 0) {
2829 session->nonce_low += 1;
2830 session->nonce_high += 1;
2834 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2835 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2836 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2837 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2839 SIVAL(state->hdr, 0, SMB2_MAGIC);
2840 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2841 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2842 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2843 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2844 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2845 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2846 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2847 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2848 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2849 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2850 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2851 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2853 state->vector[0] = (struct iovec) {
2854 .iov_base = state->nbt_hdr,
2855 .iov_len = sizeof(state->nbt_hdr)
2858 if (do_encryption) {
2859 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2860 .iov_base = state->tf,
2861 .iov_len = sizeof(state->tf)
2863 } else {
2864 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2865 .iov_base = NULL,
2866 .iov_len = 0
2870 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2871 .iov_base = state->hdr,
2872 .iov_len = sizeof(state->hdr)
2875 memcpy(state->body, body, body_len);
2877 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2878 .iov_base = state->body,
2879 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2883 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2886 ok = smb2_setup_nbt_length(state->vector,
2887 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2888 if (!ok) {
2889 return NT_STATUS_INVALID_PARAMETER_MIX;
2892 if (do_encryption) {
2893 DATA_BLOB encryption_key = session->global->encryption_key;
2895 status = smb2_signing_encrypt_pdu(encryption_key,
2896 xconn->smb2.server.cipher,
2897 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2898 SMBD_SMB2_NUM_IOV_PER_REQ);
2899 if (!NT_STATUS_IS_OK(status)) {
2900 return status;
2904 state->queue_entry.mem_ctx = state;
2905 state->queue_entry.vector = state->vector;
2906 state->queue_entry.count = ARRAY_SIZE(state->vector);
2907 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2908 xconn->smb2.send_queue_len++;
2910 status = smbd_smb2_flush_send_queue(xconn);
2911 if (!NT_STATUS_IS_OK(status)) {
2912 return status;
2915 return NT_STATUS_OK;
2918 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2919 struct smbXsrv_session *session,
2920 struct smbXsrv_tcon *tcon,
2921 struct smbXsrv_open *op,
2922 uint8_t oplock_level)
2924 uint8_t body[0x18];
2926 SSVAL(body, 0x00, sizeof(body));
2927 SCVAL(body, 0x02, oplock_level);
2928 SCVAL(body, 0x03, 0); /* reserved */
2929 SIVAL(body, 0x04, 0); /* reserved */
2930 SBVAL(body, 0x08, op->global->open_persistent_id);
2931 SBVAL(body, 0x10, op->global->open_volatile_id);
2933 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2936 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
2937 uint16_t new_epoch,
2938 uint32_t lease_flags,
2939 struct smb2_lease_key *lease_key,
2940 uint32_t current_lease_state,
2941 uint32_t new_lease_state)
2943 uint8_t body[0x2c];
2945 SSVAL(body, 0x00, sizeof(body));
2946 SSVAL(body, 0x02, new_epoch);
2947 SIVAL(body, 0x04, lease_flags);
2948 SBVAL(body, 0x08, lease_key->data[0]);
2949 SBVAL(body, 0x10, lease_key->data[1]);
2950 SIVAL(body, 0x18, current_lease_state);
2951 SIVAL(body, 0x1c, new_lease_state);
2952 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
2953 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2954 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2956 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
2959 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2961 NTSTATUS status;
2962 uint32_t flags;
2963 uint64_t file_id_persistent;
2964 uint64_t file_id_volatile;
2965 struct smbXsrv_open *op = NULL;
2966 struct files_struct *fsp = NULL;
2967 const uint8_t *body = NULL;
2970 * This is only called with a pktbuf
2971 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2972 * bytes
2975 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2976 /* Transform header. Cannot recvfile. */
2977 return false;
2979 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2980 /* Not SMB2. Normal error path will cope. */
2981 return false;
2983 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2984 /* Not SMB2. Normal error path will cope. */
2985 return false;
2987 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2988 /* Needs to be a WRITE. */
2989 return false;
2991 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2992 /* Chained. Cannot recvfile. */
2993 return false;
2995 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2996 if (flags & SMB2_HDR_FLAG_CHAINED) {
2997 /* Chained. Cannot recvfile. */
2998 return false;
3000 if (flags & SMB2_HDR_FLAG_SIGNED) {
3001 /* Signed. Cannot recvfile. */
3002 return false;
3005 body = &state->pktbuf[SMB2_HDR_BODY];
3007 file_id_persistent = BVAL(body, 0x10);
3008 file_id_volatile = BVAL(body, 0x18);
3010 status = smb2srv_open_lookup(state->req->xconn,
3011 file_id_persistent,
3012 file_id_volatile,
3013 0, /* now */
3014 &op);
3015 if (!NT_STATUS_IS_OK(status)) {
3016 return false;
3019 fsp = op->compat;
3020 if (fsp == NULL) {
3021 return false;
3023 if (fsp->conn == NULL) {
3024 return false;
3027 if (IS_IPC(fsp->conn)) {
3028 return false;
3030 if (IS_PRINT(fsp->conn)) {
3031 return false;
3034 DEBUG(10,("Doing recvfile write len = %u\n",
3035 (unsigned int)(state->pktfull - state->pktlen)));
3037 return true;
3040 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3042 struct smbd_server_connection *sconn = xconn->client->sconn;
3043 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3044 size_t max_send_queue_len;
3045 size_t cur_send_queue_len;
3047 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3049 * we're not supposed to do any io
3051 return NT_STATUS_OK;
3054 if (state->req != NULL) {
3056 * if there is already a tstream_readv_pdu
3057 * pending, we are done.
3059 return NT_STATUS_OK;
3062 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3063 cur_send_queue_len = xconn->smb2.send_queue_len;
3065 if (cur_send_queue_len > max_send_queue_len) {
3067 * if we have a lot of requests to send,
3068 * we wait until they are on the wire until we
3069 * ask for the next request.
3071 return NT_STATUS_OK;
3074 /* ask for the next request */
3075 ZERO_STRUCTP(state);
3076 state->req = smbd_smb2_request_allocate(xconn);
3077 if (state->req == NULL) {
3078 return NT_STATUS_NO_MEMORY;
3080 state->req->sconn = sconn;
3081 state->req->xconn = xconn;
3082 state->min_recv_size = lp_min_receive_file_size();
3084 TEVENT_FD_READABLE(xconn->transport.fde);
3086 return NT_STATUS_OK;
3089 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3090 const uint8_t *inpdu, size_t size)
3092 struct smbd_server_connection *sconn = xconn->client->sconn;
3093 NTSTATUS status;
3094 struct smbd_smb2_request *req = NULL;
3096 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3097 (unsigned int)size));
3099 status = smbd_initialize_smb2(xconn);
3100 if (!NT_STATUS_IS_OK(status)) {
3101 smbd_server_connection_terminate(xconn, nt_errstr(status));
3102 return;
3105 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3106 if (!NT_STATUS_IS_OK(status)) {
3107 smbd_server_connection_terminate(xconn, nt_errstr(status));
3108 return;
3111 status = smbd_smb2_request_validate(req);
3112 if (!NT_STATUS_IS_OK(status)) {
3113 smbd_server_connection_terminate(xconn, nt_errstr(status));
3114 return;
3117 status = smbd_smb2_request_setup_out(req);
3118 if (!NT_STATUS_IS_OK(status)) {
3119 smbd_server_connection_terminate(xconn, nt_errstr(status));
3120 return;
3123 #ifdef WITH_PROFILE
3125 * this was already counted at the SMB1 layer =>
3126 * smbd_smb2_request_dispatch() should not count it twice.
3128 if (profile_p->values.request_stats.count > 0) {
3129 profile_p->values.request_stats.count--;
3131 #endif
3132 status = smbd_smb2_request_dispatch(req);
3133 if (!NT_STATUS_IS_OK(status)) {
3134 smbd_server_connection_terminate(xconn, nt_errstr(status));
3135 return;
3138 status = smbd_smb2_request_next_incoming(xconn);
3139 if (!NT_STATUS_IS_OK(status)) {
3140 smbd_server_connection_terminate(xconn, nt_errstr(status));
3141 return;
3144 sconn->num_requests++;
3147 static int socket_error_from_errno(int ret,
3148 int sys_errno,
3149 bool *retry)
3151 *retry = false;
3153 if (ret >= 0) {
3154 return 0;
3157 if (ret != -1) {
3158 return EIO;
3161 if (sys_errno == 0) {
3162 return EIO;
3165 if (sys_errno == EINTR) {
3166 *retry = true;
3167 return sys_errno;
3170 if (sys_errno == EINPROGRESS) {
3171 *retry = true;
3172 return sys_errno;
3175 if (sys_errno == EAGAIN) {
3176 *retry = true;
3177 return sys_errno;
3180 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3181 if (sys_errno == ENOMEM) {
3182 *retry = true;
3183 return sys_errno;
3186 #ifdef EWOULDBLOCK
3187 #if EWOULDBLOCK != EAGAIN
3188 if (sys_errno == EWOULDBLOCK) {
3189 *retry = true;
3190 return sys_errno;
3192 #endif
3193 #endif
3195 return sys_errno;
3198 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3200 int ret;
3201 int err;
3202 bool retry;
3204 if (xconn->smb2.send_queue == NULL) {
3205 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3206 return NT_STATUS_OK;
3209 while (xconn->smb2.send_queue != NULL) {
3210 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3211 bool ok;
3213 if (e->sendfile_header != NULL) {
3214 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3215 size_t size = 0;
3216 size_t i = 0;
3217 uint8_t *buf;
3219 for (i=0; i < e->count; i++) {
3220 size += e->vector[i].iov_len;
3223 if (size <= e->sendfile_header->length) {
3224 buf = e->sendfile_header->data;
3225 } else {
3226 buf = talloc_array(e->mem_ctx, uint8_t, size);
3227 if (buf == NULL) {
3228 return NT_STATUS_NO_MEMORY;
3232 size = 0;
3233 for (i=0; i < e->count; i++) {
3234 memcpy(buf+size,
3235 e->vector[i].iov_base,
3236 e->vector[i].iov_len);
3237 size += e->vector[i].iov_len;
3240 e->sendfile_header->data = buf;
3241 e->sendfile_header->length = size;
3242 e->sendfile_status = &status;
3243 e->count = 0;
3245 xconn->smb2.send_queue_len--;
3246 DLIST_REMOVE(xconn->smb2.send_queue, e);
3248 * This triggers the sendfile path via
3249 * the destructor.
3251 talloc_free(e->mem_ctx);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 return status;
3256 continue;
3259 ret = writev(xconn->transport.sock, e->vector, e->count);
3260 if (ret == 0) {
3261 /* propagate end of file */
3262 return NT_STATUS_INTERNAL_ERROR;
3264 err = socket_error_from_errno(ret, errno, &retry);
3265 if (retry) {
3266 /* retry later */
3267 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3268 return NT_STATUS_OK;
3270 if (err != 0) {
3271 return map_nt_error_from_unix_common(err);
3274 ok = iov_advance(&e->vector, &e->count, ret);
3275 if (!ok) {
3276 return NT_STATUS_INTERNAL_ERROR;
3279 if (e->count > 0) {
3280 /* we have more to write */
3281 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3282 return NT_STATUS_OK;
3285 xconn->smb2.send_queue_len--;
3286 DLIST_REMOVE(xconn->smb2.send_queue, e);
3287 talloc_free(e->mem_ctx);
3290 return NT_STATUS_OK;
3293 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3294 uint16_t fde_flags)
3296 struct smbd_server_connection *sconn = xconn->client->sconn;
3297 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3298 struct smbd_smb2_request *req = NULL;
3299 size_t min_recvfile_size = UINT32_MAX;
3300 int ret;
3301 int err;
3302 bool retry;
3303 NTSTATUS status;
3304 NTTIME now;
3306 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3308 * we're not supposed to do any io
3310 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3311 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3312 return NT_STATUS_OK;
3315 if (fde_flags & TEVENT_FD_WRITE) {
3316 status = smbd_smb2_flush_send_queue(xconn);
3317 if (!NT_STATUS_IS_OK(status)) {
3318 return status;
3322 if (!(fde_flags & TEVENT_FD_READ)) {
3323 return NT_STATUS_OK;
3326 if (state->req == NULL) {
3327 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3328 return NT_STATUS_OK;
3331 again:
3332 if (!state->hdr.done) {
3333 state->hdr.done = true;
3335 state->vector.iov_base = (void *)state->hdr.nbt;
3336 state->vector.iov_len = NBT_HDR_SIZE;
3339 ret = readv(xconn->transport.sock, &state->vector, 1);
3340 if (ret == 0) {
3341 /* propagate end of file */
3342 return NT_STATUS_END_OF_FILE;
3344 err = socket_error_from_errno(ret, errno, &retry);
3345 if (retry) {
3346 /* retry later */
3347 TEVENT_FD_READABLE(xconn->transport.fde);
3348 return NT_STATUS_OK;
3350 if (err != 0) {
3351 return map_nt_error_from_unix_common(err);
3354 if (ret < state->vector.iov_len) {
3355 uint8_t *base;
3356 base = (uint8_t *)state->vector.iov_base;
3357 base += ret;
3358 state->vector.iov_base = (void *)base;
3359 state->vector.iov_len -= ret;
3360 /* we have more to read */
3361 TEVENT_FD_READABLE(xconn->transport.fde);
3362 return NT_STATUS_OK;
3365 if (state->pktlen > 0) {
3366 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3368 * Not a possible receivefile write.
3369 * Read the rest of the data.
3371 state->doing_receivefile = false;
3373 state->pktbuf = talloc_realloc(state->req,
3374 state->pktbuf,
3375 uint8_t,
3376 state->pktfull);
3377 if (state->pktbuf == NULL) {
3378 return NT_STATUS_NO_MEMORY;
3381 state->vector.iov_base = (void *)(state->pktbuf +
3382 state->pktlen);
3383 state->vector.iov_len = (state->pktfull -
3384 state->pktlen);
3386 state->pktlen = state->pktfull;
3387 goto again;
3391 * Either this is a receivefile write so we've
3392 * done a short read, or if not we have all the data.
3394 goto got_full;
3398 * Now we analyze the NBT header
3400 if (state->hdr.nbt[0] != 0x00) {
3401 state->min_recv_size = 0;
3403 state->pktfull = smb2_len(state->hdr.nbt);
3404 if (state->pktfull == 0) {
3405 goto got_full;
3408 if (state->min_recv_size != 0) {
3409 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3410 min_recvfile_size += state->min_recv_size;
3413 if (state->pktfull > min_recvfile_size) {
3415 * Might be a receivefile write. Read the SMB2 HEADER +
3416 * SMB2_WRITE header first. Set 'doing_receivefile'
3417 * as we're *attempting* receivefile write. If this
3418 * turns out not to be a SMB2_WRITE request or otherwise
3419 * not suitable then we'll just read the rest of the data
3420 * the next time this function is called.
3422 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3423 state->doing_receivefile = true;
3424 } else {
3425 state->pktlen = state->pktfull;
3428 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3429 if (state->pktbuf == NULL) {
3430 return NT_STATUS_NO_MEMORY;
3433 state->vector.iov_base = (void *)state->pktbuf;
3434 state->vector.iov_len = state->pktlen;
3436 goto again;
3438 got_full:
3440 if (state->hdr.nbt[0] != 0x00) {
3441 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3442 state->hdr.nbt[0]));
3444 req = state->req;
3445 ZERO_STRUCTP(state);
3446 state->req = req;
3447 state->min_recv_size = lp_min_receive_file_size();
3448 req = NULL;
3449 goto again;
3452 req = state->req;
3453 state->req = NULL;
3455 req->request_time = timeval_current();
3456 now = timeval_to_nttime(&req->request_time);
3458 status = smbd_smb2_inbuf_parse_compound(xconn,
3459 now,
3460 state->pktbuf,
3461 state->pktlen,
3462 req,
3463 &req->in.vector,
3464 &req->in.vector_count);
3465 if (!NT_STATUS_IS_OK(status)) {
3466 return status;
3469 if (state->doing_receivefile) {
3470 req->smb1req = talloc_zero(req, struct smb_request);
3471 if (req->smb1req == NULL) {
3472 return NT_STATUS_NO_MEMORY;
3474 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3477 ZERO_STRUCTP(state);
3479 req->current_idx = 1;
3481 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3482 req->current_idx, req->in.vector_count));
3484 status = smbd_smb2_request_validate(req);
3485 if (!NT_STATUS_IS_OK(status)) {
3486 return status;
3489 status = smbd_smb2_request_setup_out(req);
3490 if (!NT_STATUS_IS_OK(status)) {
3491 return status;
3494 status = smbd_smb2_request_dispatch(req);
3495 if (!NT_STATUS_IS_OK(status)) {
3496 return status;
3499 sconn->num_requests++;
3501 /* The timeout_processing function isn't run nearly
3502 often enough to implement 'max log size' without
3503 overrunning the size of the file by many megabytes.
3504 This is especially true if we are running at debug
3505 level 10. Checking every 50 SMB2s is a nice
3506 tradeoff of performance vs log file size overrun. */
3508 if ((sconn->num_requests % 50) == 0 &&
3509 need_to_check_log_size()) {
3510 change_to_root_user();
3511 check_log_size();
3514 status = smbd_smb2_request_next_incoming(xconn);
3515 if (!NT_STATUS_IS_OK(status)) {
3516 return status;
3519 return NT_STATUS_OK;
3522 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3523 struct tevent_fd *fde,
3524 uint16_t flags,
3525 void *private_data)
3527 struct smbXsrv_connection *xconn =
3528 talloc_get_type_abort(private_data,
3529 struct smbXsrv_connection);
3530 NTSTATUS status;
3532 status = smbd_smb2_io_handler(xconn, flags);
3533 if (!NT_STATUS_IS_OK(status)) {
3534 smbd_server_connection_terminate(xconn, nt_errstr(status));
3535 return;