lib: Fix CID 1034723 Explicit null dereferenced
[Samba.git] / source3 / smbd / smb2_server.c
bloba8d54cbd019e6958bb05a7cfcad49f38018f0860
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 NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1462 uint64_t *new_nonce_high,
1463 uint64_t *new_nonce_low)
1465 uint64_t nonce_high;
1466 uint64_t nonce_low;
1468 session->nonce_low += 1;
1469 if (session->nonce_low == 0) {
1470 session->nonce_low += 1;
1471 session->nonce_high += 1;
1475 * CCM and GCM algorithms must never have their
1476 * nonce wrap, or the security of the whole
1477 * communication and the keys is destroyed.
1478 * We must drop the connection once we have
1479 * transfered too much data.
1481 * NOTE: We assume nonces greater than 8 bytes.
1483 if (session->nonce_high >= session->nonce_high_max) {
1484 return NT_STATUS_ENCRYPTION_FAILED;
1487 nonce_high = session->nonce_high_random;
1488 nonce_high += session->nonce_high;
1489 nonce_low = session->nonce_low;
1491 *new_nonce_high = nonce_high;
1492 *new_nonce_low = nonce_low;
1493 return NT_STATUS_OK;
1496 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1497 struct tevent_timer *te,
1498 struct timeval current_time,
1499 void *private_data)
1501 struct smbd_smb2_request *req =
1502 talloc_get_type_abort(private_data,
1503 struct smbd_smb2_request);
1504 struct smbXsrv_connection *xconn = req->xconn;
1505 struct smbd_smb2_request_pending_state *state = NULL;
1506 uint8_t *outhdr = NULL;
1507 const uint8_t *inhdr = NULL;
1508 uint8_t *tf = NULL;
1509 size_t tf_len = 0;
1510 uint8_t *hdr = NULL;
1511 uint8_t *body = NULL;
1512 uint8_t *dyn = NULL;
1513 uint32_t flags = 0;
1514 uint64_t session_id = 0;
1515 uint64_t message_id = 0;
1516 uint64_t nonce_high = 0;
1517 uint64_t nonce_low = 0;
1518 uint64_t async_id = 0;
1519 NTSTATUS status;
1520 bool ok;
1522 TALLOC_FREE(req->async_te);
1524 /* Ensure our final reply matches the interim one. */
1525 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1526 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1527 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1528 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1529 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1531 async_id = message_id; /* keep it simple for now... */
1533 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1534 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1536 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1537 "going async\n",
1538 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1539 (unsigned long long)async_id ));
1542 * What we send is identical to a smbd_smb2_request_error
1543 * packet with an error status of STATUS_PENDING. Make use
1544 * of this fact sometime when refactoring. JRA.
1547 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1548 if (state == NULL) {
1549 smbd_server_connection_terminate(xconn,
1550 nt_errstr(NT_STATUS_NO_MEMORY));
1551 return;
1554 tf = state->buf + NBT_HDR_SIZE;
1555 tf_len = SMB2_TF_HDR_SIZE;
1557 hdr = tf + SMB2_TF_HDR_SIZE;
1558 body = hdr + SMB2_HDR_BODY;
1559 dyn = body + 8;
1561 if (req->do_encryption) {
1562 status = smb2_get_new_nonce(req->session,
1563 &nonce_high,
1564 &nonce_low);
1565 if (!NT_STATUS_IS_OK(status)) {
1566 smbd_server_connection_terminate(xconn,
1567 nt_errstr(status));
1568 return;
1572 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1573 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1574 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1575 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1577 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1578 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1579 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1580 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1581 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1583 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1584 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1585 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1586 SBVAL(hdr, SMB2_HDR_PID, async_id);
1587 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1588 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1589 memcpy(hdr+SMB2_HDR_SIGNATURE,
1590 outhdr+SMB2_HDR_SIGNATURE, 16);
1592 SSVAL(body, 0x00, 0x08 + 1);
1594 SCVAL(body, 0x02, 0);
1595 SCVAL(body, 0x03, 0);
1596 SIVAL(body, 0x04, 0);
1597 /* Match W2K8R2... */
1598 SCVAL(dyn, 0x00, 0x21);
1600 state->vector[0].iov_base = (void *)state->buf;
1601 state->vector[0].iov_len = NBT_HDR_SIZE;
1603 if (req->do_encryption) {
1604 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1605 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1606 } else {
1607 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1608 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1611 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1612 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1614 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1615 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1617 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1618 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1620 ok = smb2_setup_nbt_length(state->vector,
1621 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1622 if (!ok) {
1623 smbd_server_connection_terminate(
1624 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1625 return;
1628 /* Ensure we correctly go through crediting. Grant
1629 the credits now, and zero credits on the final
1630 response. */
1631 smb2_set_operation_credit(req->xconn,
1632 SMBD_SMB2_IN_HDR_IOV(req),
1633 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1635 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1637 if (DEBUGLVL(10)) {
1638 int i;
1640 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1641 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1642 (unsigned int)i,
1643 (unsigned int)ARRAY_SIZE(state->vector),
1644 (unsigned int)state->vector[i].iov_len);
1648 if (req->do_encryption) {
1649 struct smbXsrv_session *x = req->session;
1650 DATA_BLOB encryption_key = x->global->encryption_key;
1652 status = smb2_signing_encrypt_pdu(encryption_key,
1653 xconn->smb2.server.cipher,
1654 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1655 SMBD_SMB2_NUM_IOV_PER_REQ);
1656 if (!NT_STATUS_IS_OK(status)) {
1657 smbd_server_connection_terminate(xconn,
1658 nt_errstr(status));
1659 return;
1661 } else if (req->do_signing) {
1662 struct smbXsrv_session *x = req->session;
1663 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1665 status = smb2_signing_sign_pdu(signing_key,
1666 xconn->protocol,
1667 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1668 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1669 if (!NT_STATUS_IS_OK(status)) {
1670 smbd_server_connection_terminate(xconn,
1671 nt_errstr(status));
1672 return;
1676 state->queue_entry.mem_ctx = state;
1677 state->queue_entry.vector = state->vector;
1678 state->queue_entry.count = ARRAY_SIZE(state->vector);
1679 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1680 xconn->smb2.send_queue_len++;
1682 status = smbd_smb2_flush_send_queue(xconn);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 smbd_server_connection_terminate(xconn,
1685 nt_errstr(status));
1686 return;
1690 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1692 struct smbXsrv_connection *xconn = req->xconn;
1693 struct smbd_smb2_request *cur;
1694 const uint8_t *inhdr;
1695 uint32_t flags;
1696 uint64_t search_message_id;
1697 uint64_t search_async_id;
1698 uint64_t found_id;
1700 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1702 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1703 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1704 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1707 * we don't need the request anymore
1708 * cancel requests never have a response
1710 DLIST_REMOVE(xconn->smb2.requests, req);
1711 TALLOC_FREE(req);
1713 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1714 const uint8_t *outhdr;
1715 uint64_t message_id;
1716 uint64_t async_id;
1718 if (cur->compound_related) {
1720 * Never cancel anything in a compound request.
1721 * Way too hard to deal with the result.
1723 continue;
1726 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1728 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1729 async_id = BVAL(outhdr, SMB2_HDR_PID);
1731 if (flags & SMB2_HDR_FLAG_ASYNC) {
1732 if (search_async_id == async_id) {
1733 found_id = async_id;
1734 break;
1736 } else {
1737 if (search_message_id == message_id) {
1738 found_id = message_id;
1739 break;
1744 if (cur && cur->subreq) {
1745 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1746 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1747 "cancel opcode[%s] mid %llu\n",
1748 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1749 (unsigned long long)found_id ));
1750 tevent_req_cancel(cur->subreq);
1753 return NT_STATUS_OK;
1756 /*************************************************************
1757 Ensure an incoming tid is a valid one for us to access.
1758 Change to the associated uid credentials and chdir to the
1759 valid tid directory.
1760 *************************************************************/
1762 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1764 const uint8_t *inhdr;
1765 uint32_t in_flags;
1766 uint32_t in_tid;
1767 struct smbXsrv_tcon *tcon;
1768 NTSTATUS status;
1769 NTTIME now = timeval_to_nttime(&req->request_time);
1771 req->tcon = NULL;
1773 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1775 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1776 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1778 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1779 in_tid = req->last_tid;
1782 req->last_tid = 0;
1784 status = smb2srv_tcon_lookup(req->session,
1785 in_tid, now, &tcon);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 return status;
1790 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1791 return NT_STATUS_ACCESS_DENIED;
1794 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1795 if (!set_current_service(tcon->compat, 0, true)) {
1796 return NT_STATUS_ACCESS_DENIED;
1799 req->tcon = tcon;
1800 req->last_tid = in_tid;
1802 return NT_STATUS_OK;
1805 /*************************************************************
1806 Ensure an incoming session_id is a valid one for us to access.
1807 *************************************************************/
1809 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1811 const uint8_t *inhdr;
1812 uint32_t in_flags;
1813 uint16_t in_opcode;
1814 uint64_t in_session_id;
1815 struct smbXsrv_session *session = NULL;
1816 struct auth_session_info *session_info;
1817 NTSTATUS status;
1818 NTTIME now = timeval_to_nttime(&req->request_time);
1820 req->session = NULL;
1821 req->tcon = NULL;
1823 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1825 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1826 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1827 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1829 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1830 in_session_id = req->last_session_id;
1833 req->last_session_id = 0;
1835 /* lookup an existing session */
1836 status = smb2srv_session_lookup(req->xconn,
1837 in_session_id, now,
1838 &session);
1839 if (session) {
1840 req->session = session;
1841 req->last_session_id = in_session_id;
1843 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1844 switch (in_opcode) {
1845 case SMB2_OP_SESSSETUP:
1846 status = NT_STATUS_OK;
1847 break;
1848 default:
1849 break;
1852 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1853 switch (in_opcode) {
1854 case SMB2_OP_TCON:
1855 case SMB2_OP_CREATE:
1856 case SMB2_OP_GETINFO:
1857 case SMB2_OP_SETINFO:
1858 return NT_STATUS_INVALID_HANDLE;
1859 default:
1861 * Notice the check for
1862 * (session_info == NULL)
1863 * below.
1865 status = NT_STATUS_OK;
1866 break;
1869 if (!NT_STATUS_IS_OK(status)) {
1870 return status;
1873 session_info = session->global->auth_session_info;
1874 if (session_info == NULL) {
1875 return NT_STATUS_INVALID_HANDLE;
1878 if (in_session_id != req->xconn->client->last_session_id) {
1879 req->xconn->client->last_session_id = in_session_id;
1880 set_current_user_info(session_info->unix_info->sanitized_username,
1881 session_info->unix_info->unix_name,
1882 session_info->info->domain_name);
1885 return NT_STATUS_OK;
1888 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1889 uint32_t data_length)
1891 struct smbXsrv_connection *xconn = req->xconn;
1892 uint16_t needed_charge;
1893 uint16_t credit_charge = 1;
1894 const uint8_t *inhdr;
1896 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1898 if (xconn->smb2.credits.multicredit) {
1899 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1900 credit_charge = MAX(credit_charge, 1);
1903 needed_charge = (data_length - 1)/ 65536 + 1;
1905 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1906 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1907 credit_charge, needed_charge));
1909 if (needed_charge > credit_charge) {
1910 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1911 credit_charge, needed_charge));
1912 return NT_STATUS_INVALID_PARAMETER;
1915 return NT_STATUS_OK;
1918 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1919 size_t expected_body_size)
1921 struct iovec *inhdr_v;
1922 const uint8_t *inhdr;
1923 uint16_t opcode;
1924 const uint8_t *inbody;
1925 size_t body_size;
1926 size_t min_dyn_size = expected_body_size & 0x00000001;
1927 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1930 * The following should be checked already.
1932 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1933 return NT_STATUS_INTERNAL_ERROR;
1935 if (req->current_idx > max_idx) {
1936 return NT_STATUS_INTERNAL_ERROR;
1939 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1940 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1941 return NT_STATUS_INTERNAL_ERROR;
1943 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1944 return NT_STATUS_INTERNAL_ERROR;
1947 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1948 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1950 switch (opcode) {
1951 case SMB2_OP_IOCTL:
1952 case SMB2_OP_GETINFO:
1953 min_dyn_size = 0;
1954 break;
1955 case SMB2_OP_WRITE:
1956 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1957 if (req->smb1req->unread_bytes < min_dyn_size) {
1958 return NT_STATUS_INVALID_PARAMETER;
1961 min_dyn_size = 0;
1963 break;
1967 * Now check the expected body size,
1968 * where the last byte might be in the
1969 * dynamic section..
1971 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1972 return NT_STATUS_INVALID_PARAMETER;
1974 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1975 return NT_STATUS_INVALID_PARAMETER;
1978 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1980 body_size = SVAL(inbody, 0x00);
1981 if (body_size != expected_body_size) {
1982 return NT_STATUS_INVALID_PARAMETER;
1985 return NT_STATUS_OK;
1988 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1990 struct smbXsrv_connection *xconn = req->xconn;
1991 const struct smbd_smb2_dispatch_table *call = NULL;
1992 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1993 const uint8_t *inhdr;
1994 uint16_t opcode;
1995 uint32_t flags;
1996 uint64_t mid;
1997 NTSTATUS status;
1998 NTSTATUS session_status;
1999 uint32_t allowed_flags;
2000 NTSTATUS return_value;
2001 struct smbXsrv_session *x = NULL;
2002 bool signing_required = false;
2003 bool encryption_required = false;
2005 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2007 DO_PROFILE_INC(request);
2009 /* TODO: verify more things */
2011 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2012 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2013 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2014 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2015 smb2_opcode_name(opcode),
2016 (unsigned long long)mid));
2018 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2020 * once the protocol is negotiated
2021 * SMB2_OP_NEGPROT is not allowed anymore
2023 if (opcode == SMB2_OP_NEGPROT) {
2024 /* drop the connection */
2025 return NT_STATUS_INVALID_PARAMETER;
2027 } else {
2029 * if the protocol is not negotiated yet
2030 * only SMB2_OP_NEGPROT is allowed.
2032 if (opcode != SMB2_OP_NEGPROT) {
2033 /* drop the connection */
2034 return NT_STATUS_INVALID_PARAMETER;
2039 * Check if the client provided a valid session id,
2040 * if so smbd_smb2_request_check_session() calls
2041 * set_current_user_info().
2043 * As some command don't require a valid session id
2044 * we defer the check of the session_status
2046 session_status = smbd_smb2_request_check_session(req);
2047 x = req->session;
2048 if (x != NULL) {
2049 signing_required = x->global->signing_required;
2050 encryption_required = x->global->encryption_required;
2053 req->do_signing = false;
2054 req->do_encryption = false;
2055 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2056 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2057 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2059 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2060 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2061 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2062 (unsigned long long)x->global->session_wire_id,
2063 (unsigned long long)tf_session_id));
2065 * TODO: windows allows this...
2066 * should we drop the connection?
2068 * For now we just return ACCESS_DENIED
2069 * (Windows clients never trigger this)
2070 * and wait for an update of [MS-SMB2].
2072 return smbd_smb2_request_error(req,
2073 NT_STATUS_ACCESS_DENIED);
2076 req->do_encryption = true;
2079 if (encryption_required && !req->do_encryption) {
2080 return smbd_smb2_request_error(req,
2081 NT_STATUS_ACCESS_DENIED);
2084 call = smbd_smb2_call(opcode);
2085 if (call == NULL) {
2086 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2089 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2090 SMB2_HDR_FLAG_SIGNED |
2091 SMB2_HDR_FLAG_DFS;
2092 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2093 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2095 if (opcode == SMB2_OP_NEGPROT) {
2096 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2097 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2100 if (opcode == SMB2_OP_CANCEL) {
2101 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2103 if ((flags & ~allowed_flags) != 0) {
2104 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2107 if (flags & SMB2_HDR_FLAG_CHAINED) {
2109 * This check is mostly for giving the correct error code
2110 * for compounded requests.
2112 if (!NT_STATUS_IS_OK(session_status)) {
2113 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2115 } else {
2116 req->compat_chain_fsp = NULL;
2119 if (req->do_encryption) {
2120 signing_required = false;
2121 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2122 DATA_BLOB signing_key = data_blob_null;
2124 if (x == NULL) {
2126 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2127 * If the SMB2 header of the SMB2 NEGOTIATE
2128 * request has the SMB2_FLAGS_SIGNED bit set in the
2129 * Flags field, the server MUST fail the request
2130 * with STATUS_INVALID_PARAMETER.
2132 * Microsoft test tool checks this.
2135 if ((opcode == SMB2_OP_NEGPROT) &&
2136 (flags & SMB2_HDR_FLAG_SIGNED)) {
2137 status = NT_STATUS_INVALID_PARAMETER;
2138 } else {
2139 status = NT_STATUS_USER_SESSION_DELETED;
2141 return smbd_smb2_request_error(req, status);
2144 signing_key = smbd_smb2_signing_key(x, xconn);
2147 * If we have a signing key, we should
2148 * sign the response
2150 if (signing_key.length > 0) {
2151 req->do_signing = true;
2154 status = smb2_signing_check_pdu(signing_key,
2155 xconn->protocol,
2156 SMBD_SMB2_IN_HDR_IOV(req),
2157 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2158 if (!NT_STATUS_IS_OK(status)) {
2159 return smbd_smb2_request_error(req, status);
2163 * Now that we know the request was correctly signed
2164 * we have to sign the response too.
2166 req->do_signing = true;
2168 if (!NT_STATUS_IS_OK(session_status)) {
2169 return smbd_smb2_request_error(req, session_status);
2171 } else if (opcode == SMB2_OP_CANCEL) {
2172 /* Cancel requests are allowed to skip the signing */
2173 } else if (signing_required) {
2175 * If signing is required we try to sign
2176 * a possible error response
2178 req->do_signing = true;
2179 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2182 if (flags & SMB2_HDR_FLAG_CHAINED) {
2183 req->compound_related = true;
2186 if (call->need_session) {
2187 if (!NT_STATUS_IS_OK(session_status)) {
2188 return smbd_smb2_request_error(req, session_status);
2192 if (call->need_tcon) {
2193 SMB_ASSERT(call->need_session);
2196 * This call needs to be run as user.
2198 * smbd_smb2_request_check_tcon()
2199 * calls change_to_user() on success.
2201 status = smbd_smb2_request_check_tcon(req);
2202 if (!NT_STATUS_IS_OK(status)) {
2203 return smbd_smb2_request_error(req, status);
2205 if (req->tcon->global->encryption_required) {
2206 encryption_required = true;
2208 if (encryption_required && !req->do_encryption) {
2209 return smbd_smb2_request_error(req,
2210 NT_STATUS_ACCESS_DENIED);
2214 if (call->fileid_ofs != 0) {
2215 size_t needed = call->fileid_ofs + 16;
2216 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2217 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2218 uint64_t file_id_persistent;
2219 uint64_t file_id_volatile;
2220 struct files_struct *fsp;
2222 SMB_ASSERT(call->need_tcon);
2224 if (needed > body_size) {
2225 return smbd_smb2_request_error(req,
2226 NT_STATUS_INVALID_PARAMETER);
2229 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2230 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2232 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2233 if (fsp == NULL) {
2234 if (!call->allow_invalid_fileid) {
2235 return smbd_smb2_request_error(req,
2236 NT_STATUS_FILE_CLOSED);
2239 if (file_id_persistent != UINT64_MAX) {
2240 return smbd_smb2_request_error(req,
2241 NT_STATUS_FILE_CLOSED);
2243 if (file_id_volatile != UINT64_MAX) {
2244 return smbd_smb2_request_error(req,
2245 NT_STATUS_FILE_CLOSED);
2250 if (call->as_root) {
2251 SMB_ASSERT(call->fileid_ofs == 0);
2252 /* This call needs to be run as root */
2253 change_to_root_user();
2254 } else {
2255 SMB_ASSERT(call->need_tcon);
2258 #define _INBYTES(_r) \
2259 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2261 switch (opcode) {
2262 case SMB2_OP_NEGPROT:
2263 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2264 req->profile, _INBYTES(req));
2265 return_value = smbd_smb2_request_process_negprot(req);
2266 break;
2268 case SMB2_OP_SESSSETUP:
2269 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2270 req->profile, _INBYTES(req));
2271 return_value = smbd_smb2_request_process_sesssetup(req);
2272 break;
2274 case SMB2_OP_LOGOFF:
2275 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2276 req->profile, _INBYTES(req));
2277 return_value = smbd_smb2_request_process_logoff(req);
2278 break;
2280 case SMB2_OP_TCON:
2281 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2282 req->profile, _INBYTES(req));
2283 return_value = smbd_smb2_request_process_tcon(req);
2284 break;
2286 case SMB2_OP_TDIS:
2287 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2288 req->profile, _INBYTES(req));
2289 return_value = smbd_smb2_request_process_tdis(req);
2290 break;
2292 case SMB2_OP_CREATE:
2293 if (req->subreq == NULL) {
2294 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2295 req->profile, _INBYTES(req));
2296 } else {
2297 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2299 return_value = smbd_smb2_request_process_create(req);
2300 break;
2302 case SMB2_OP_CLOSE:
2303 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2304 req->profile, _INBYTES(req));
2305 return_value = smbd_smb2_request_process_close(req);
2306 break;
2308 case SMB2_OP_FLUSH:
2309 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2310 req->profile, _INBYTES(req));
2311 return_value = smbd_smb2_request_process_flush(req);
2312 break;
2314 case SMB2_OP_READ:
2315 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2316 req->profile, _INBYTES(req));
2317 return_value = smbd_smb2_request_process_read(req);
2318 break;
2320 case SMB2_OP_WRITE:
2321 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2322 req->profile, _INBYTES(req));
2323 return_value = smbd_smb2_request_process_write(req);
2324 break;
2326 case SMB2_OP_LOCK:
2327 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2328 req->profile, _INBYTES(req));
2329 return_value = smbd_smb2_request_process_lock(req);
2330 break;
2332 case SMB2_OP_IOCTL:
2333 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2334 req->profile, _INBYTES(req));
2335 return_value = smbd_smb2_request_process_ioctl(req);
2336 break;
2338 case SMB2_OP_CANCEL:
2339 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2340 req->profile, _INBYTES(req));
2341 return_value = smbd_smb2_request_process_cancel(req);
2342 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2343 break;
2345 case SMB2_OP_KEEPALIVE:
2346 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2347 req->profile, _INBYTES(req));
2348 return_value = smbd_smb2_request_process_keepalive(req);
2349 break;
2351 case SMB2_OP_QUERY_DIRECTORY:
2352 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2353 req->profile, _INBYTES(req));
2354 return_value = smbd_smb2_request_process_query_directory(req);
2355 break;
2357 case SMB2_OP_NOTIFY:
2358 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2359 req->profile, _INBYTES(req));
2360 return_value = smbd_smb2_request_process_notify(req);
2361 break;
2363 case SMB2_OP_GETINFO:
2364 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2365 req->profile, _INBYTES(req));
2366 return_value = smbd_smb2_request_process_getinfo(req);
2367 break;
2369 case SMB2_OP_SETINFO:
2370 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2371 req->profile, _INBYTES(req));
2372 return_value = smbd_smb2_request_process_setinfo(req);
2373 break;
2375 case SMB2_OP_BREAK:
2376 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2377 req->profile, _INBYTES(req));
2378 return_value = smbd_smb2_request_process_break(req);
2379 break;
2381 default:
2382 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2383 break;
2385 return return_value;
2388 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2390 struct smbXsrv_connection *xconn = req->xconn;
2391 int first_idx = 1;
2392 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2393 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2394 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2395 NTSTATUS status;
2396 bool ok;
2398 req->subreq = NULL;
2399 TALLOC_FREE(req->async_te);
2401 if (req->do_encryption &&
2402 (firsttf->iov_len == 0) &&
2403 (req->first_key.length == 0) &&
2404 (req->session != NULL) &&
2405 (req->session->global->encryption_key.length != 0))
2407 DATA_BLOB encryption_key = req->session->global->encryption_key;
2408 uint8_t *tf;
2409 uint64_t session_id = req->session->global->session_wire_id;
2410 uint64_t nonce_high;
2411 uint64_t nonce_low;
2413 status = smb2_get_new_nonce(req->session,
2414 &nonce_high,
2415 &nonce_low);
2416 if (!NT_STATUS_IS_OK(status)) {
2417 return status;
2421 * We need to place the SMB2_TRANSFORM header before the
2422 * first SMB2 header
2426 * we need to remember the encryption key
2427 * and defer the signing/encryption until
2428 * we are sure that we do not change
2429 * the header again.
2431 req->first_key = data_blob_dup_talloc(req, encryption_key);
2432 if (req->first_key.data == NULL) {
2433 return NT_STATUS_NO_MEMORY;
2436 tf = talloc_zero_array(req, uint8_t,
2437 SMB2_TF_HDR_SIZE);
2438 if (tf == NULL) {
2439 return NT_STATUS_NO_MEMORY;
2442 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2443 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2444 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2445 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2447 firsttf->iov_base = (void *)tf;
2448 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2451 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2452 (req->last_key.length > 0) &&
2453 (firsttf->iov_len == 0))
2455 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2456 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2459 * As we are sure the header of the last request in the
2460 * compound chain will not change, we can to sign here
2461 * with the last signing key we remembered.
2463 status = smb2_signing_sign_pdu(req->last_key,
2464 xconn->protocol,
2465 lasthdr,
2466 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 return status;
2471 if (req->last_key.length > 0) {
2472 data_blob_clear_free(&req->last_key);
2475 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2476 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2478 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2480 if (req->current_idx < req->out.vector_count) {
2482 * We must process the remaining compound
2483 * SMB2 requests before any new incoming SMB2
2484 * requests. This is because incoming SMB2
2485 * requests may include a cancel for a
2486 * compound request we haven't processed
2487 * yet.
2489 struct tevent_immediate *im = tevent_create_immediate(req);
2490 if (!im) {
2491 return NT_STATUS_NO_MEMORY;
2494 if (req->do_signing && firsttf->iov_len == 0) {
2495 struct smbXsrv_session *x = req->session;
2496 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2499 * we need to remember the signing key
2500 * and defer the signing until
2501 * we are sure that we do not change
2502 * the header again.
2504 req->last_key = data_blob_dup_talloc(req, signing_key);
2505 if (req->last_key.data == NULL) {
2506 return NT_STATUS_NO_MEMORY;
2510 tevent_schedule_immediate(im,
2511 req->sconn->ev_ctx,
2512 smbd_smb2_request_dispatch_immediate,
2513 req);
2514 return NT_STATUS_OK;
2517 if (req->compound_related) {
2518 req->compound_related = false;
2521 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2522 if (!ok) {
2523 return NT_STATUS_INVALID_PARAMETER_MIX;
2526 /* Set credit for these operations (zero credits if this
2527 is a final reply for an async operation). */
2528 smb2_calculate_credits(req, req);
2531 * now check if we need to sign the current response
2533 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2534 status = smb2_signing_encrypt_pdu(req->first_key,
2535 xconn->smb2.server.cipher,
2536 firsttf,
2537 req->out.vector_count - first_idx);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 return status;
2541 } else if (req->do_signing) {
2542 struct smbXsrv_session *x = req->session;
2543 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2545 status = smb2_signing_sign_pdu(signing_key,
2546 xconn->protocol,
2547 outhdr,
2548 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 return status;
2553 if (req->first_key.length > 0) {
2554 data_blob_clear_free(&req->first_key);
2557 if (req->preauth != NULL) {
2558 struct hc_sha512state sctx;
2559 int i;
2561 samba_SHA512_Init(&sctx);
2562 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2563 sizeof(req->preauth->sha512_value));
2564 for (i = 1; i < req->in.vector_count; i++) {
2565 samba_SHA512_Update(&sctx,
2566 req->in.vector[i].iov_base,
2567 req->in.vector[i].iov_len);
2569 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2571 samba_SHA512_Init(&sctx);
2572 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2573 sizeof(req->preauth->sha512_value));
2574 for (i = 1; i < req->out.vector_count; i++) {
2575 samba_SHA512_Update(&sctx,
2576 req->out.vector[i].iov_base,
2577 req->out.vector[i].iov_len);
2579 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2581 req->preauth = NULL;
2584 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2585 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2586 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2587 /* Dynamic part is NULL. Chop it off,
2588 We're going to send it via sendfile. */
2589 req->out.vector_count -= 1;
2593 * We're done with this request -
2594 * move it off the "being processed" queue.
2596 DLIST_REMOVE(xconn->smb2.requests, req);
2598 req->queue_entry.mem_ctx = req;
2599 req->queue_entry.vector = req->out.vector;
2600 req->queue_entry.count = req->out.vector_count;
2601 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2602 xconn->smb2.send_queue_len++;
2604 status = smbd_smb2_flush_send_queue(xconn);
2605 if (!NT_STATUS_IS_OK(status)) {
2606 return status;
2609 return NT_STATUS_OK;
2612 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2614 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2615 struct tevent_immediate *im,
2616 void *private_data)
2618 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2619 struct smbd_smb2_request);
2620 struct smbXsrv_connection *xconn = req->xconn;
2621 NTSTATUS status;
2623 TALLOC_FREE(im);
2625 if (DEBUGLEVEL >= 10) {
2626 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2627 req->current_idx, req->in.vector_count));
2628 print_req_vectors(req);
2631 status = smbd_smb2_request_dispatch(req);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 smbd_server_connection_terminate(xconn, nt_errstr(status));
2634 return;
2637 status = smbd_smb2_request_next_incoming(xconn);
2638 if (!NT_STATUS_IS_OK(status)) {
2639 smbd_server_connection_terminate(xconn, nt_errstr(status));
2640 return;
2644 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2645 NTSTATUS status,
2646 DATA_BLOB body, DATA_BLOB *dyn,
2647 const char *location)
2649 uint8_t *outhdr;
2650 struct iovec *outbody_v;
2651 struct iovec *outdyn_v;
2652 uint32_t next_command_ofs;
2654 DEBUG(10,("smbd_smb2_request_done_ex: "
2655 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2656 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2657 dyn ? "yes": "no",
2658 (unsigned int)(dyn ? dyn->length : 0),
2659 location));
2661 if (body.length < 2) {
2662 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2665 if ((body.length % 2) != 0) {
2666 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2669 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2670 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2671 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2673 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2674 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2676 outbody_v->iov_base = (void *)body.data;
2677 outbody_v->iov_len = body.length;
2679 if (dyn) {
2680 outdyn_v->iov_base = (void *)dyn->data;
2681 outdyn_v->iov_len = dyn->length;
2682 } else {
2683 outdyn_v->iov_base = NULL;
2684 outdyn_v->iov_len = 0;
2688 * See if we need to recalculate the offset to the next response
2690 * Note that all responses may require padding (including the very last
2691 * one).
2693 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
2694 next_command_ofs = SMB2_HDR_BODY;
2695 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2696 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2699 if ((next_command_ofs % 8) != 0) {
2700 size_t pad_size = 8 - (next_command_ofs % 8);
2701 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2703 * if the dyn buffer is empty
2704 * we can use it to add padding
2706 uint8_t *pad;
2708 pad = talloc_zero_array(req,
2709 uint8_t, pad_size);
2710 if (pad == NULL) {
2711 return smbd_smb2_request_error(req,
2712 NT_STATUS_NO_MEMORY);
2715 outdyn_v->iov_base = (void *)pad;
2716 outdyn_v->iov_len = pad_size;
2717 } else {
2719 * For now we copy the dynamic buffer
2720 * and add the padding to the new buffer
2722 size_t old_size;
2723 uint8_t *old_dyn;
2724 size_t new_size;
2725 uint8_t *new_dyn;
2727 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2728 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2730 new_size = old_size + pad_size;
2731 new_dyn = talloc_zero_array(req,
2732 uint8_t, new_size);
2733 if (new_dyn == NULL) {
2734 return smbd_smb2_request_error(req,
2735 NT_STATUS_NO_MEMORY);
2738 memcpy(new_dyn, old_dyn, old_size);
2739 memset(new_dyn + old_size, 0, pad_size);
2741 outdyn_v->iov_base = (void *)new_dyn;
2742 outdyn_v->iov_len = new_size;
2744 next_command_ofs += pad_size;
2747 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
2748 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2749 } else {
2750 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2752 return smbd_smb2_request_reply(req);
2755 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2756 NTSTATUS status,
2757 DATA_BLOB *info,
2758 const char *location)
2760 struct smbXsrv_connection *xconn = req->xconn;
2761 DATA_BLOB body;
2762 DATA_BLOB _dyn;
2763 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2764 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2766 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2767 req->current_idx, nt_errstr(status), info ? " +info" : "",
2768 location));
2770 if (unread_bytes) {
2771 /* Recvfile error. Drain incoming socket. */
2772 size_t ret;
2774 errno = 0;
2775 ret = drain_socket(xconn->transport.sock, unread_bytes);
2776 if (ret != unread_bytes) {
2777 NTSTATUS error;
2779 if (errno == 0) {
2780 error = NT_STATUS_IO_DEVICE_ERROR;
2781 } else {
2782 error = map_nt_error_from_unix_common(errno);
2785 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2786 "ret[%u] errno[%d] => %s\n",
2787 (unsigned)unread_bytes,
2788 (unsigned)ret, errno, nt_errstr(error)));
2789 return error;
2793 body.data = outhdr + SMB2_HDR_BODY;
2794 body.length = 8;
2795 SSVAL(body.data, 0, 9);
2797 if (info) {
2798 SIVAL(body.data, 0x04, info->length);
2799 } else {
2800 /* Allocated size of req->out.vector[i].iov_base
2801 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2802 * 1 byte without having to do an alloc.
2804 info = &_dyn;
2805 info->data = ((uint8_t *)outhdr) +
2806 OUTVEC_ALLOC_SIZE - 1;
2807 info->length = 1;
2808 SCVAL(info->data, 0, 0);
2812 * Note: Even if there is an error, continue to process the request.
2813 * per MS-SMB2.
2816 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2820 struct smbd_smb2_send_break_state {
2821 struct smbd_smb2_send_queue queue_entry;
2822 uint8_t nbt_hdr[NBT_HDR_SIZE];
2823 uint8_t tf[SMB2_TF_HDR_SIZE];
2824 uint8_t hdr[SMB2_HDR_BODY];
2825 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2826 uint8_t body[1];
2829 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2830 struct smbXsrv_session *session,
2831 struct smbXsrv_tcon *tcon,
2832 const uint8_t *body,
2833 size_t body_len)
2835 struct smbd_smb2_send_break_state *state;
2836 bool do_encryption = false;
2837 uint64_t session_wire_id = 0;
2838 uint64_t nonce_high = 0;
2839 uint64_t nonce_low = 0;
2840 NTSTATUS status;
2841 size_t statelen;
2842 bool ok;
2844 if (session != NULL) {
2845 session_wire_id = session->global->session_wire_id;
2846 do_encryption = session->global->encryption_required;
2847 if (tcon->global->encryption_required) {
2848 do_encryption = true;
2852 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2853 body_len;
2855 state = talloc_zero_size(xconn, statelen);
2856 if (state == NULL) {
2857 return NT_STATUS_NO_MEMORY;
2859 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2861 if (do_encryption) {
2862 status = smb2_get_new_nonce(session,
2863 &nonce_high,
2864 &nonce_low);
2865 if (!NT_STATUS_IS_OK(status)) {
2866 return status;
2870 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2871 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2872 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2873 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2875 SIVAL(state->hdr, 0, SMB2_MAGIC);
2876 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2877 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2878 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2879 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2880 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2881 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2882 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2883 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2884 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2885 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2886 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2887 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2889 state->vector[0] = (struct iovec) {
2890 .iov_base = state->nbt_hdr,
2891 .iov_len = sizeof(state->nbt_hdr)
2894 if (do_encryption) {
2895 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2896 .iov_base = state->tf,
2897 .iov_len = sizeof(state->tf)
2899 } else {
2900 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2901 .iov_base = NULL,
2902 .iov_len = 0
2906 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2907 .iov_base = state->hdr,
2908 .iov_len = sizeof(state->hdr)
2911 memcpy(state->body, body, body_len);
2913 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2914 .iov_base = state->body,
2915 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2919 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2922 ok = smb2_setup_nbt_length(state->vector,
2923 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2924 if (!ok) {
2925 return NT_STATUS_INVALID_PARAMETER_MIX;
2928 if (do_encryption) {
2929 DATA_BLOB encryption_key = session->global->encryption_key;
2931 status = smb2_signing_encrypt_pdu(encryption_key,
2932 xconn->smb2.server.cipher,
2933 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2934 SMBD_SMB2_NUM_IOV_PER_REQ);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 return status;
2940 state->queue_entry.mem_ctx = state;
2941 state->queue_entry.vector = state->vector;
2942 state->queue_entry.count = ARRAY_SIZE(state->vector);
2943 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2944 xconn->smb2.send_queue_len++;
2946 status = smbd_smb2_flush_send_queue(xconn);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 return status;
2951 return NT_STATUS_OK;
2954 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2955 struct smbXsrv_session *session,
2956 struct smbXsrv_tcon *tcon,
2957 struct smbXsrv_open *op,
2958 uint8_t oplock_level)
2960 uint8_t body[0x18];
2962 SSVAL(body, 0x00, sizeof(body));
2963 SCVAL(body, 0x02, oplock_level);
2964 SCVAL(body, 0x03, 0); /* reserved */
2965 SIVAL(body, 0x04, 0); /* reserved */
2966 SBVAL(body, 0x08, op->global->open_persistent_id);
2967 SBVAL(body, 0x10, op->global->open_volatile_id);
2969 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2972 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
2973 uint16_t new_epoch,
2974 uint32_t lease_flags,
2975 struct smb2_lease_key *lease_key,
2976 uint32_t current_lease_state,
2977 uint32_t new_lease_state)
2979 uint8_t body[0x2c];
2981 SSVAL(body, 0x00, sizeof(body));
2982 SSVAL(body, 0x02, new_epoch);
2983 SIVAL(body, 0x04, lease_flags);
2984 SBVAL(body, 0x08, lease_key->data[0]);
2985 SBVAL(body, 0x10, lease_key->data[1]);
2986 SIVAL(body, 0x18, current_lease_state);
2987 SIVAL(body, 0x1c, new_lease_state);
2988 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
2989 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
2990 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
2992 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
2995 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2997 NTSTATUS status;
2998 uint32_t flags;
2999 uint64_t file_id_persistent;
3000 uint64_t file_id_volatile;
3001 struct smbXsrv_open *op = NULL;
3002 struct files_struct *fsp = NULL;
3003 const uint8_t *body = NULL;
3006 * This is only called with a pktbuf
3007 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3008 * bytes
3011 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3012 /* Transform header. Cannot recvfile. */
3013 return false;
3015 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3016 /* Not SMB2. Normal error path will cope. */
3017 return false;
3019 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3020 /* Not SMB2. Normal error path will cope. */
3021 return false;
3023 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3024 /* Needs to be a WRITE. */
3025 return false;
3027 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3028 /* Chained. Cannot recvfile. */
3029 return false;
3031 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3032 if (flags & SMB2_HDR_FLAG_CHAINED) {
3033 /* Chained. Cannot recvfile. */
3034 return false;
3036 if (flags & SMB2_HDR_FLAG_SIGNED) {
3037 /* Signed. Cannot recvfile. */
3038 return false;
3041 body = &state->pktbuf[SMB2_HDR_BODY];
3043 file_id_persistent = BVAL(body, 0x10);
3044 file_id_volatile = BVAL(body, 0x18);
3046 status = smb2srv_open_lookup(state->req->xconn,
3047 file_id_persistent,
3048 file_id_volatile,
3049 0, /* now */
3050 &op);
3051 if (!NT_STATUS_IS_OK(status)) {
3052 return false;
3055 fsp = op->compat;
3056 if (fsp == NULL) {
3057 return false;
3059 if (fsp->conn == NULL) {
3060 return false;
3063 if (IS_IPC(fsp->conn)) {
3064 return false;
3066 if (IS_PRINT(fsp->conn)) {
3067 return false;
3070 DEBUG(10,("Doing recvfile write len = %u\n",
3071 (unsigned int)(state->pktfull - state->pktlen)));
3073 return true;
3076 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3078 struct smbd_server_connection *sconn = xconn->client->sconn;
3079 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3080 size_t max_send_queue_len;
3081 size_t cur_send_queue_len;
3083 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3085 * we're not supposed to do any io
3087 return NT_STATUS_OK;
3090 if (state->req != NULL) {
3092 * if there is already a tstream_readv_pdu
3093 * pending, we are done.
3095 return NT_STATUS_OK;
3098 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3099 cur_send_queue_len = xconn->smb2.send_queue_len;
3101 if (cur_send_queue_len > max_send_queue_len) {
3103 * if we have a lot of requests to send,
3104 * we wait until they are on the wire until we
3105 * ask for the next request.
3107 return NT_STATUS_OK;
3110 /* ask for the next request */
3111 ZERO_STRUCTP(state);
3112 state->req = smbd_smb2_request_allocate(xconn);
3113 if (state->req == NULL) {
3114 return NT_STATUS_NO_MEMORY;
3116 state->req->sconn = sconn;
3117 state->req->xconn = xconn;
3118 state->min_recv_size = lp_min_receive_file_size();
3120 TEVENT_FD_READABLE(xconn->transport.fde);
3122 return NT_STATUS_OK;
3125 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3126 const uint8_t *inpdu, size_t size)
3128 struct smbd_server_connection *sconn = xconn->client->sconn;
3129 NTSTATUS status;
3130 struct smbd_smb2_request *req = NULL;
3132 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3133 (unsigned int)size));
3135 status = smbd_initialize_smb2(xconn);
3136 if (!NT_STATUS_IS_OK(status)) {
3137 smbd_server_connection_terminate(xconn, nt_errstr(status));
3138 return;
3141 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 smbd_server_connection_terminate(xconn, nt_errstr(status));
3144 return;
3147 status = smbd_smb2_request_validate(req);
3148 if (!NT_STATUS_IS_OK(status)) {
3149 smbd_server_connection_terminate(xconn, nt_errstr(status));
3150 return;
3153 status = smbd_smb2_request_setup_out(req);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 smbd_server_connection_terminate(xconn, nt_errstr(status));
3156 return;
3159 #ifdef WITH_PROFILE
3161 * this was already counted at the SMB1 layer =>
3162 * smbd_smb2_request_dispatch() should not count it twice.
3164 if (profile_p->values.request_stats.count > 0) {
3165 profile_p->values.request_stats.count--;
3167 #endif
3168 status = smbd_smb2_request_dispatch(req);
3169 if (!NT_STATUS_IS_OK(status)) {
3170 smbd_server_connection_terminate(xconn, nt_errstr(status));
3171 return;
3174 status = smbd_smb2_request_next_incoming(xconn);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 smbd_server_connection_terminate(xconn, nt_errstr(status));
3177 return;
3180 sconn->num_requests++;
3183 static int socket_error_from_errno(int ret,
3184 int sys_errno,
3185 bool *retry)
3187 *retry = false;
3189 if (ret >= 0) {
3190 return 0;
3193 if (ret != -1) {
3194 return EIO;
3197 if (sys_errno == 0) {
3198 return EIO;
3201 if (sys_errno == EINTR) {
3202 *retry = true;
3203 return sys_errno;
3206 if (sys_errno == EINPROGRESS) {
3207 *retry = true;
3208 return sys_errno;
3211 if (sys_errno == EAGAIN) {
3212 *retry = true;
3213 return sys_errno;
3216 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3217 if (sys_errno == ENOMEM) {
3218 *retry = true;
3219 return sys_errno;
3222 #ifdef EWOULDBLOCK
3223 #if EWOULDBLOCK != EAGAIN
3224 if (sys_errno == EWOULDBLOCK) {
3225 *retry = true;
3226 return sys_errno;
3228 #endif
3229 #endif
3231 return sys_errno;
3234 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3236 int ret;
3237 int err;
3238 bool retry;
3240 if (xconn->smb2.send_queue == NULL) {
3241 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3242 return NT_STATUS_OK;
3245 while (xconn->smb2.send_queue != NULL) {
3246 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3247 bool ok;
3249 if (e->sendfile_header != NULL) {
3250 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3251 size_t size = 0;
3252 size_t i = 0;
3253 uint8_t *buf;
3255 for (i=0; i < e->count; i++) {
3256 size += e->vector[i].iov_len;
3259 if (size <= e->sendfile_header->length) {
3260 buf = e->sendfile_header->data;
3261 } else {
3262 buf = talloc_array(e->mem_ctx, uint8_t, size);
3263 if (buf == NULL) {
3264 return NT_STATUS_NO_MEMORY;
3268 size = 0;
3269 for (i=0; i < e->count; i++) {
3270 memcpy(buf+size,
3271 e->vector[i].iov_base,
3272 e->vector[i].iov_len);
3273 size += e->vector[i].iov_len;
3276 e->sendfile_header->data = buf;
3277 e->sendfile_header->length = size;
3278 e->sendfile_status = &status;
3279 e->count = 0;
3281 xconn->smb2.send_queue_len--;
3282 DLIST_REMOVE(xconn->smb2.send_queue, e);
3284 * This triggers the sendfile path via
3285 * the destructor.
3287 talloc_free(e->mem_ctx);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 return status;
3292 continue;
3295 ret = writev(xconn->transport.sock, e->vector, e->count);
3296 if (ret == 0) {
3297 /* propagate end of file */
3298 return NT_STATUS_INTERNAL_ERROR;
3300 err = socket_error_from_errno(ret, errno, &retry);
3301 if (retry) {
3302 /* retry later */
3303 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3304 return NT_STATUS_OK;
3306 if (err != 0) {
3307 return map_nt_error_from_unix_common(err);
3310 ok = iov_advance(&e->vector, &e->count, ret);
3311 if (!ok) {
3312 return NT_STATUS_INTERNAL_ERROR;
3315 if (e->count > 0) {
3316 /* we have more to write */
3317 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3318 return NT_STATUS_OK;
3321 xconn->smb2.send_queue_len--;
3322 DLIST_REMOVE(xconn->smb2.send_queue, e);
3323 talloc_free(e->mem_ctx);
3326 return NT_STATUS_OK;
3329 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3330 uint16_t fde_flags)
3332 struct smbd_server_connection *sconn = xconn->client->sconn;
3333 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3334 struct smbd_smb2_request *req = NULL;
3335 size_t min_recvfile_size = UINT32_MAX;
3336 int ret;
3337 int err;
3338 bool retry;
3339 NTSTATUS status;
3340 NTTIME now;
3342 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3344 * we're not supposed to do any io
3346 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3347 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3348 return NT_STATUS_OK;
3351 if (fde_flags & TEVENT_FD_WRITE) {
3352 status = smbd_smb2_flush_send_queue(xconn);
3353 if (!NT_STATUS_IS_OK(status)) {
3354 return status;
3358 if (!(fde_flags & TEVENT_FD_READ)) {
3359 return NT_STATUS_OK;
3362 if (state->req == NULL) {
3363 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3364 return NT_STATUS_OK;
3367 again:
3368 if (!state->hdr.done) {
3369 state->hdr.done = true;
3371 state->vector.iov_base = (void *)state->hdr.nbt;
3372 state->vector.iov_len = NBT_HDR_SIZE;
3375 ret = readv(xconn->transport.sock, &state->vector, 1);
3376 if (ret == 0) {
3377 /* propagate end of file */
3378 return NT_STATUS_END_OF_FILE;
3380 err = socket_error_from_errno(ret, errno, &retry);
3381 if (retry) {
3382 /* retry later */
3383 TEVENT_FD_READABLE(xconn->transport.fde);
3384 return NT_STATUS_OK;
3386 if (err != 0) {
3387 return map_nt_error_from_unix_common(err);
3390 if (ret < state->vector.iov_len) {
3391 uint8_t *base;
3392 base = (uint8_t *)state->vector.iov_base;
3393 base += ret;
3394 state->vector.iov_base = (void *)base;
3395 state->vector.iov_len -= ret;
3396 /* we have more to read */
3397 TEVENT_FD_READABLE(xconn->transport.fde);
3398 return NT_STATUS_OK;
3401 if (state->pktlen > 0) {
3402 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3404 * Not a possible receivefile write.
3405 * Read the rest of the data.
3407 state->doing_receivefile = false;
3409 state->pktbuf = talloc_realloc(state->req,
3410 state->pktbuf,
3411 uint8_t,
3412 state->pktfull);
3413 if (state->pktbuf == NULL) {
3414 return NT_STATUS_NO_MEMORY;
3417 state->vector.iov_base = (void *)(state->pktbuf +
3418 state->pktlen);
3419 state->vector.iov_len = (state->pktfull -
3420 state->pktlen);
3422 state->pktlen = state->pktfull;
3423 goto again;
3427 * Either this is a receivefile write so we've
3428 * done a short read, or if not we have all the data.
3430 goto got_full;
3434 * Now we analyze the NBT header
3436 if (state->hdr.nbt[0] != 0x00) {
3437 state->min_recv_size = 0;
3439 state->pktfull = smb2_len(state->hdr.nbt);
3440 if (state->pktfull == 0) {
3441 goto got_full;
3444 if (state->min_recv_size != 0) {
3445 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3446 min_recvfile_size += state->min_recv_size;
3449 if (state->pktfull > min_recvfile_size) {
3451 * Might be a receivefile write. Read the SMB2 HEADER +
3452 * SMB2_WRITE header first. Set 'doing_receivefile'
3453 * as we're *attempting* receivefile write. If this
3454 * turns out not to be a SMB2_WRITE request or otherwise
3455 * not suitable then we'll just read the rest of the data
3456 * the next time this function is called.
3458 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3459 state->doing_receivefile = true;
3460 } else {
3461 state->pktlen = state->pktfull;
3464 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3465 if (state->pktbuf == NULL) {
3466 return NT_STATUS_NO_MEMORY;
3469 state->vector.iov_base = (void *)state->pktbuf;
3470 state->vector.iov_len = state->pktlen;
3472 goto again;
3474 got_full:
3476 if (state->hdr.nbt[0] != 0x00) {
3477 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3478 state->hdr.nbt[0]));
3480 req = state->req;
3481 ZERO_STRUCTP(state);
3482 state->req = req;
3483 state->min_recv_size = lp_min_receive_file_size();
3484 req = NULL;
3485 goto again;
3488 req = state->req;
3489 state->req = NULL;
3491 req->request_time = timeval_current();
3492 now = timeval_to_nttime(&req->request_time);
3494 status = smbd_smb2_inbuf_parse_compound(xconn,
3495 now,
3496 state->pktbuf,
3497 state->pktlen,
3498 req,
3499 &req->in.vector,
3500 &req->in.vector_count);
3501 if (!NT_STATUS_IS_OK(status)) {
3502 return status;
3505 if (state->doing_receivefile) {
3506 req->smb1req = talloc_zero(req, struct smb_request);
3507 if (req->smb1req == NULL) {
3508 return NT_STATUS_NO_MEMORY;
3510 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3513 ZERO_STRUCTP(state);
3515 req->current_idx = 1;
3517 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3518 req->current_idx, req->in.vector_count));
3520 status = smbd_smb2_request_validate(req);
3521 if (!NT_STATUS_IS_OK(status)) {
3522 return status;
3525 status = smbd_smb2_request_setup_out(req);
3526 if (!NT_STATUS_IS_OK(status)) {
3527 return status;
3530 status = smbd_smb2_request_dispatch(req);
3531 if (!NT_STATUS_IS_OK(status)) {
3532 return status;
3535 sconn->num_requests++;
3537 /* The timeout_processing function isn't run nearly
3538 often enough to implement 'max log size' without
3539 overrunning the size of the file by many megabytes.
3540 This is especially true if we are running at debug
3541 level 10. Checking every 50 SMB2s is a nice
3542 tradeoff of performance vs log file size overrun. */
3544 if ((sconn->num_requests % 50) == 0 &&
3545 need_to_check_log_size()) {
3546 change_to_root_user();
3547 check_log_size();
3550 status = smbd_smb2_request_next_incoming(xconn);
3551 if (!NT_STATUS_IS_OK(status)) {
3552 return status;
3555 return NT_STATUS_OK;
3558 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3559 struct tevent_fd *fde,
3560 uint16_t flags,
3561 void *private_data)
3563 struct smbXsrv_connection *xconn =
3564 talloc_get_type_abort(private_data,
3565 struct smbXsrv_connection);
3566 NTSTATUS status;
3568 status = smbd_smb2_io_handler(xconn, flags);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 smbd_server_connection_terminate(xconn, nt_errstr(status));
3571 return;