nfs4acls: Use talloc_realloc()
[Samba.git] / source3 / smbd / smb2_server.c
bloba53ddf8527d81fa8aaa79e0a43eeca1a1a25fdc5
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_conn(xconn, uid, now,
397 &s);
398 if (s == NULL) {
399 DEBUG(1, ("invalid session[%llu] in "
400 "SMB2_TRANSFORM header\n",
401 (unsigned long long)uid));
402 TALLOC_FREE(iov_alloc);
403 return NT_STATUS_USER_SESSION_DELETED;
406 tf_iov[0].iov_base = (void *)tf;
407 tf_iov[0].iov_len = tf_len;
408 tf_iov[1].iov_base = (void *)hdr;
409 tf_iov[1].iov_len = enc_len;
411 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
412 xconn->smb2.server.cipher,
413 tf_iov, 2);
414 if (!NT_STATUS_IS_OK(status)) {
415 TALLOC_FREE(iov_alloc);
416 return status;
419 verified_buflen = taken + enc_len;
420 len = enc_len;
424 * We need the header plus the body length field
427 if (len < SMB2_HDR_BODY + 2) {
428 DEBUG(10, ("%d bytes left, expected at least %d\n",
429 (int)len, SMB2_HDR_BODY));
430 goto inval;
432 if (IVAL(hdr, 0) != SMB2_MAGIC) {
433 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
434 IVAL(hdr, 0)));
435 goto inval;
437 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
438 DEBUG(10, ("Got HDR len %d, expected %d\n",
439 SVAL(hdr, 4), SMB2_HDR_BODY));
440 goto inval;
443 full_size = len;
444 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
445 body_size = SVAL(hdr, SMB2_HDR_BODY);
447 if (next_command_ofs != 0) {
448 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
449 goto inval;
451 if (next_command_ofs > full_size) {
452 goto inval;
454 full_size = next_command_ofs;
456 if (body_size < 2) {
457 goto inval;
459 body_size &= 0xfffe;
461 if (body_size > (full_size - SMB2_HDR_BODY)) {
463 * let the caller handle the error
465 body_size = full_size - SMB2_HDR_BODY;
467 body = hdr + SMB2_HDR_BODY;
468 dyn = body + body_size;
469 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
471 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
472 struct iovec *iov_tmp = NULL;
474 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
475 struct iovec,
476 num_iov +
477 SMBD_SMB2_NUM_IOV_PER_REQ);
478 if (iov_tmp == NULL) {
479 TALLOC_FREE(iov_alloc);
480 return NT_STATUS_NO_MEMORY;
483 if (iov_alloc == NULL) {
484 memcpy(iov_tmp,
485 req->in._vector,
486 sizeof(req->in._vector));
489 iov = iov_tmp;
491 cur = &iov[num_iov];
492 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
494 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
495 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
496 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
497 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
498 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
499 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
500 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
501 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
503 taken += full_size;
506 *piov = iov;
507 *pnum_iov = num_iov;
508 return NT_STATUS_OK;
510 inval:
511 if (iov != req->in._vector) {
512 TALLOC_FREE(iov);
514 return NT_STATUS_INVALID_PARAMETER;
517 static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
518 const uint8_t *_inpdu, size_t size,
519 struct smbd_smb2_request **_req)
521 struct smbd_server_connection *sconn = xconn->client->sconn;
522 struct smbd_smb2_request *req;
523 uint32_t protocol_version;
524 uint8_t *inpdu = NULL;
525 const uint8_t *inhdr = NULL;
526 uint16_t cmd;
527 uint32_t next_command_ofs;
528 NTSTATUS status;
529 NTTIME now;
531 if (size < (SMB2_HDR_BODY + 2)) {
532 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
533 return NT_STATUS_INVALID_PARAMETER;
536 inhdr = _inpdu;
538 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
539 if (protocol_version != SMB2_MAGIC) {
540 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
541 protocol_version));
542 return NT_STATUS_INVALID_PARAMETER;
545 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
546 if (cmd != SMB2_OP_NEGPROT) {
547 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
548 cmd));
549 return NT_STATUS_INVALID_PARAMETER;
552 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
553 if (next_command_ofs != 0) {
554 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
555 next_command_ofs));
556 return NT_STATUS_INVALID_PARAMETER;
559 req = smbd_smb2_request_allocate(xconn);
560 if (req == NULL) {
561 return NT_STATUS_NO_MEMORY;
563 req->sconn = sconn;
564 req->xconn = xconn;
566 inpdu = talloc_memdup(req, _inpdu, size);
567 if (inpdu == NULL) {
568 return NT_STATUS_NO_MEMORY;
571 req->request_time = timeval_current();
572 now = timeval_to_nttime(&req->request_time);
574 status = smbd_smb2_inbuf_parse_compound(xconn,
575 now,
576 inpdu,
577 size,
578 req, &req->in.vector,
579 &req->in.vector_count);
580 if (!NT_STATUS_IS_OK(status)) {
581 TALLOC_FREE(req);
582 return status;
585 req->current_idx = 1;
587 *_req = req;
588 return NT_STATUS_OK;
591 static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
592 uint64_t message_id, uint64_t seq_id)
594 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
595 unsigned int offset;
596 uint64_t seq_tmp;
598 seq_tmp = xconn->smb2.credits.seq_low;
599 if (seq_id < seq_tmp) {
600 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
601 "%llu (sequence id %llu) "
602 "(granted = %u, low = %llu, range = %u)\n",
603 (unsigned long long)message_id,
604 (unsigned long long)seq_id,
605 (unsigned int)xconn->smb2.credits.granted,
606 (unsigned long long)xconn->smb2.credits.seq_low,
607 (unsigned int)xconn->smb2.credits.seq_range));
608 return false;
611 seq_tmp += xconn->smb2.credits.seq_range;
612 if (seq_id >= seq_tmp) {
613 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
614 "%llu (sequence id %llu) "
615 "(granted = %u, low = %llu, range = %u)\n",
616 (unsigned long long)message_id,
617 (unsigned long long)seq_id,
618 (unsigned int)xconn->smb2.credits.granted,
619 (unsigned long long)xconn->smb2.credits.seq_low,
620 (unsigned int)xconn->smb2.credits.seq_range));
621 return false;
624 offset = seq_id % xconn->smb2.credits.max;
626 if (bitmap_query(credits_bm, offset)) {
627 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
628 "%llu (sequence id %llu) "
629 "(granted = %u, low = %llu, range = %u) "
630 "(bm offset %u)\n",
631 (unsigned long long)message_id,
632 (unsigned long long)seq_id,
633 (unsigned int)xconn->smb2.credits.granted,
634 (unsigned long long)xconn->smb2.credits.seq_low,
635 (unsigned int)xconn->smb2.credits.seq_range,
636 offset));
637 return false;
640 /* Mark the message_ids as seen in the bitmap. */
641 bitmap_set(credits_bm, offset);
643 if (seq_id != xconn->smb2.credits.seq_low) {
644 return true;
648 * Move the window forward by all the message_id's
649 * already seen.
651 while (bitmap_query(credits_bm, offset)) {
652 DEBUG(10,("smb2_validate_sequence_number: clearing "
653 "id %llu (position %u) from bitmap\n",
654 (unsigned long long)(xconn->smb2.credits.seq_low),
655 offset));
656 bitmap_clear(credits_bm, offset);
658 xconn->smb2.credits.seq_low += 1;
659 xconn->smb2.credits.seq_range -= 1;
660 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
663 return true;
666 static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
667 const uint8_t *inhdr)
669 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
670 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
671 uint16_t credit_charge = 1;
672 uint64_t i;
674 if (opcode == SMB2_OP_CANCEL) {
675 /* SMB2_CANCEL requests by definition resend messageids. */
676 return true;
679 if (xconn->smb2.credits.multicredit) {
680 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
681 credit_charge = MAX(credit_charge, 1);
684 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
685 "credits_granted %llu, "
686 "seqnum low/range: %llu/%llu\n",
687 (unsigned long long) message_id,
688 (unsigned long long) credit_charge,
689 (unsigned long long) xconn->smb2.credits.granted,
690 (unsigned long long) xconn->smb2.credits.seq_low,
691 (unsigned long long) xconn->smb2.credits.seq_range));
693 if (xconn->smb2.credits.granted < credit_charge) {
694 DEBUG(0, ("smb2_validate_message_id: client used more "
695 "credits than granted, mid %llu, charge %llu, "
696 "credits_granted %llu, "
697 "seqnum low/range: %llu/%llu\n",
698 (unsigned long long) message_id,
699 (unsigned long long) credit_charge,
700 (unsigned long long) xconn->smb2.credits.granted,
701 (unsigned long long) xconn->smb2.credits.seq_low,
702 (unsigned long long) xconn->smb2.credits.seq_range));
703 return false;
707 * now check the message ids
709 * for multi-credit requests we need to check all current mid plus
710 * the implicit mids caused by the credit charge
711 * e.g. current mid = 15, charge 5 => mark 15-19 as used
714 for (i = 0; i <= (credit_charge-1); i++) {
715 uint64_t id = message_id + i;
716 bool ok;
718 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
719 (unsigned long long)message_id,
720 credit_charge,
721 (unsigned long long)id));
723 ok = smb2_validate_sequence_number(xconn, message_id, id);
724 if (!ok) {
725 return false;
729 /* substract used credits */
730 xconn->smb2.credits.granted -= credit_charge;
732 return true;
735 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
737 int count;
738 int idx;
740 count = req->in.vector_count;
742 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
743 /* It's not a SMB2 request */
744 return NT_STATUS_INVALID_PARAMETER;
747 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
748 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
749 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
750 const uint8_t *inhdr = NULL;
752 if (hdr->iov_len != SMB2_HDR_BODY) {
753 return NT_STATUS_INVALID_PARAMETER;
756 if (body->iov_len < 2) {
757 return NT_STATUS_INVALID_PARAMETER;
760 inhdr = (const uint8_t *)hdr->iov_base;
762 /* Check the SMB2 header */
763 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
764 return NT_STATUS_INVALID_PARAMETER;
767 if (!smb2_validate_message_id(req->xconn, inhdr)) {
768 return NT_STATUS_INVALID_PARAMETER;
772 return NT_STATUS_OK;
775 static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
776 const struct iovec *in_vector,
777 struct iovec *out_vector)
779 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
780 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
781 uint16_t credit_charge = 1;
782 uint16_t credits_requested;
783 uint32_t out_flags;
784 uint16_t cmd;
785 NTSTATUS out_status;
786 uint16_t credits_granted = 0;
787 uint64_t credits_possible;
788 uint16_t current_max_credits;
791 * first we grant only 1/16th of the max range.
793 * Windows also starts with the 1/16th and then grants
794 * more later. I was only able to trigger higher
795 * values, when using a very high credit charge.
797 * TODO: scale up depending on load, free memory
798 * or other stuff.
799 * Maybe also on the relationship between number
800 * of requests and the used sequence number.
801 * Which means we would grant more credits
802 * for client which use multi credit requests.
804 current_max_credits = xconn->smb2.credits.max / 16;
805 current_max_credits = MAX(current_max_credits, 1);
807 if (xconn->smb2.credits.multicredit) {
808 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
809 credit_charge = MAX(credit_charge, 1);
812 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
813 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
814 credits_requested = MAX(credits_requested, 1);
815 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
816 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
818 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
820 if (xconn->smb2.credits.max < credit_charge) {
821 smbd_server_connection_terminate(xconn,
822 "client error: credit charge > max credits\n");
823 return;
826 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
828 * In case we already send an async interim
829 * response, we should not grant
830 * credits on the final response.
832 credits_granted = 0;
833 } else {
834 uint16_t additional_possible =
835 xconn->smb2.credits.max - credit_charge;
836 uint16_t additional_max = 0;
837 uint16_t additional_credits = credits_requested - 1;
839 switch (cmd) {
840 case SMB2_OP_NEGPROT:
841 break;
842 case SMB2_OP_SESSSETUP:
844 * Windows 2012 RC1 starts to grant
845 * additional credits
846 * with a successful session setup
848 if (NT_STATUS_IS_OK(out_status)) {
849 additional_max = 32;
851 break;
852 default:
854 * We match windows and only grant additional credits
855 * in chunks of 32.
857 additional_max = 32;
858 break;
861 additional_max = MIN(additional_max, additional_possible);
862 additional_credits = MIN(additional_credits, additional_max);
864 credits_granted = credit_charge + additional_credits;
868 * sequence numbers should not wrap
870 * 1. calculate the possible credits until
871 * the sequence numbers start to wrap on 64-bit.
873 * 2. UINT64_MAX is used for Break Notifications.
875 * 2. truncate the possible credits to the maximum
876 * credits we want to grant to the client in total.
878 * 3. remove the range we'll already granted to the client
879 * this makes sure the client consumes the lowest sequence
880 * number, before we can grant additional credits.
882 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
883 if (credits_possible > 0) {
884 /* remove UINT64_MAX */
885 credits_possible -= 1;
887 credits_possible = MIN(credits_possible, current_max_credits);
888 credits_possible -= xconn->smb2.credits.seq_range;
890 credits_granted = MIN(credits_granted, credits_possible);
892 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
893 xconn->smb2.credits.granted += credits_granted;
894 xconn->smb2.credits.seq_range += credits_granted;
896 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
897 "granted %u, current possible/max %u/%u, "
898 "total granted/max/low/range %u/%u/%llu/%u\n",
899 (unsigned int)credits_requested,
900 (unsigned int)credit_charge,
901 (unsigned int)credits_granted,
902 (unsigned int)credits_possible,
903 (unsigned int)current_max_credits,
904 (unsigned int)xconn->smb2.credits.granted,
905 (unsigned int)xconn->smb2.credits.max,
906 (unsigned long long)xconn->smb2.credits.seq_low,
907 (unsigned int)xconn->smb2.credits.seq_range));
910 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
911 struct smbd_smb2_request *outreq)
913 int count, idx;
914 uint16_t total_credits = 0;
916 count = outreq->out.vector_count;
918 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
919 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
920 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
921 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
923 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
925 /* To match Windows, count up what we
926 just granted. */
927 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
928 /* Set to zero in all but the last reply. */
929 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
930 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
931 } else {
932 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
937 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
939 if (req->current_idx <= 1) {
940 if (size <= sizeof(req->out._body)) {
941 return data_blob_const(req->out._body, size);
945 return data_blob_talloc(req, NULL, size);
948 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
950 struct smbXsrv_connection *xconn = req->xconn;
951 TALLOC_CTX *mem_ctx;
952 struct iovec *vector;
953 int count;
954 int idx;
955 bool ok;
957 count = req->in.vector_count;
958 if (count <= ARRAY_SIZE(req->out._vector)) {
959 mem_ctx = req;
960 vector = req->out._vector;
961 } else {
962 vector = talloc_zero_array(req, struct iovec, count);
963 if (vector == NULL) {
964 return NT_STATUS_NO_MEMORY;
966 mem_ctx = vector;
969 vector[0].iov_base = req->out.nbt_hdr;
970 vector[0].iov_len = 4;
971 SIVAL(req->out.nbt_hdr, 0, 0);
973 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
974 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
975 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
976 uint8_t *outhdr = NULL;
977 uint8_t *outbody = NULL;
978 uint32_t next_command_ofs = 0;
979 struct iovec *current = &vector[idx];
981 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
982 /* we have a next command -
983 * setup for the error case. */
984 next_command_ofs = SMB2_HDR_BODY + 9;
987 if (idx == 1) {
988 outhdr = req->out._hdr;
989 } else {
990 outhdr = talloc_zero_array(mem_ctx, uint8_t,
991 OUTVEC_ALLOC_SIZE);
992 if (outhdr == NULL) {
993 return NT_STATUS_NO_MEMORY;
997 outbody = outhdr + SMB2_HDR_BODY;
1000 * SMBD_SMB2_TF_IOV_OFS might be used later
1002 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1003 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1005 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1006 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1008 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1009 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1011 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1012 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1014 /* setup the SMB2 header */
1015 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1016 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1017 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1018 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1019 SIVAL(outhdr, SMB2_HDR_STATUS,
1020 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1021 SSVAL(outhdr, SMB2_HDR_OPCODE,
1022 SVAL(inhdr, SMB2_HDR_OPCODE));
1023 SIVAL(outhdr, SMB2_HDR_FLAGS,
1024 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1025 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1026 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1027 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1028 SIVAL(outhdr, SMB2_HDR_PID,
1029 IVAL(inhdr, SMB2_HDR_PID));
1030 SIVAL(outhdr, SMB2_HDR_TID,
1031 IVAL(inhdr, SMB2_HDR_TID));
1032 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1033 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1034 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1035 inhdr + SMB2_HDR_SIGNATURE, 16);
1037 /* setup error body header */
1038 SSVAL(outbody, 0x00, 0x08 + 1);
1039 SSVAL(outbody, 0x02, 0);
1040 SIVAL(outbody, 0x04, 0);
1043 req->out.vector = vector;
1044 req->out.vector_count = count;
1046 /* setup the length of the NBT packet */
1047 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1048 if (!ok) {
1049 return NT_STATUS_INVALID_PARAMETER_MIX;
1052 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1054 return NT_STATUS_OK;
1057 void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1058 const char *reason,
1059 const char *location)
1061 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1062 reason, location));
1063 exit_server_cleanly(reason);
1066 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1067 struct iovec *outvec,
1068 const struct iovec *srcvec)
1070 const uint8_t *srctf;
1071 size_t srctf_len;
1072 const uint8_t *srchdr;
1073 size_t srchdr_len;
1074 const uint8_t *srcbody;
1075 size_t srcbody_len;
1076 const uint8_t *expected_srcbody;
1077 const uint8_t *srcdyn;
1078 size_t srcdyn_len;
1079 const uint8_t *expected_srcdyn;
1080 uint8_t *dsttf;
1081 uint8_t *dsthdr;
1082 uint8_t *dstbody;
1083 uint8_t *dstdyn;
1085 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1086 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1087 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1088 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1089 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1090 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1091 expected_srcbody = srchdr + SMB2_HDR_BODY;
1092 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1093 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1094 expected_srcdyn = srcbody + 8;
1096 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1097 return false;
1100 if (srchdr_len != SMB2_HDR_BODY) {
1101 return false;
1104 if (srctf_len == SMB2_TF_HDR_SIZE) {
1105 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1106 if (dsttf == NULL) {
1107 return false;
1109 } else {
1110 dsttf = NULL;
1112 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1113 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1115 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1116 * be allocated with size OUTVEC_ALLOC_SIZE. */
1118 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1119 if (dsthdr == NULL) {
1120 return false;
1122 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1123 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1126 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1127 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1128 * then duplicate this. Else use talloc_memdup().
1131 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1132 dstbody = dsthdr + SMB2_HDR_BODY;
1133 } else {
1134 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1135 if (dstbody == NULL) {
1136 return false;
1139 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1140 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1143 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1144 * pointing to
1145 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1146 * then duplicate this. Else use talloc_memdup().
1149 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1150 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1151 } else if (srcdyn == NULL) {
1152 dstdyn = NULL;
1153 } else {
1154 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1155 if (dstdyn == NULL) {
1156 return false;
1159 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1160 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1162 return true;
1165 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1167 struct smbd_smb2_request *newreq = NULL;
1168 struct iovec *outvec = NULL;
1169 int count = req->out.vector_count;
1170 int i;
1171 bool ok;
1173 newreq = smbd_smb2_request_allocate(req->xconn);
1174 if (!newreq) {
1175 return NULL;
1178 newreq->sconn = req->sconn;
1179 newreq->xconn = req->xconn;
1180 newreq->session = req->session;
1181 newreq->do_encryption = req->do_encryption;
1182 newreq->do_signing = req->do_signing;
1183 newreq->current_idx = req->current_idx;
1185 outvec = talloc_zero_array(newreq, struct iovec, count);
1186 if (!outvec) {
1187 TALLOC_FREE(newreq);
1188 return NULL;
1190 newreq->out.vector = outvec;
1191 newreq->out.vector_count = count;
1193 /* Setup the outvec's identically to req. */
1194 outvec[0].iov_base = newreq->out.nbt_hdr;
1195 outvec[0].iov_len = 4;
1196 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1198 /* Setup the vectors identically to the ones in req. */
1199 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1200 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1201 break;
1205 if (i < count) {
1206 /* Alloc failed. */
1207 TALLOC_FREE(newreq);
1208 return NULL;
1211 ok = smb2_setup_nbt_length(newreq->out.vector,
1212 newreq->out.vector_count);
1213 if (!ok) {
1214 TALLOC_FREE(newreq);
1215 return NULL;
1218 return newreq;
1221 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1223 struct smbXsrv_connection *xconn = req->xconn;
1224 int first_idx = 1;
1225 struct iovec *firsttf = NULL;
1226 struct iovec *outhdr_v = NULL;
1227 uint8_t *outhdr = NULL;
1228 struct smbd_smb2_request *nreq = NULL;
1229 NTSTATUS status;
1230 bool ok;
1232 /* Create a new smb2 request we'll use
1233 for the interim return. */
1234 nreq = dup_smb2_req(req);
1235 if (!nreq) {
1236 return NT_STATUS_NO_MEMORY;
1239 /* Lose the last X out vectors. They're the
1240 ones we'll be using for the async reply. */
1241 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1243 ok = smb2_setup_nbt_length(nreq->out.vector,
1244 nreq->out.vector_count);
1245 if (!ok) {
1246 return NT_STATUS_INVALID_PARAMETER_MIX;
1249 /* Step back to the previous reply. */
1250 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1251 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1252 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1253 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1254 /* And end the chain. */
1255 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1257 /* Calculate outgoing credits */
1258 smb2_calculate_credits(req, nreq);
1260 if (DEBUGLEVEL >= 10) {
1261 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1262 (unsigned int)nreq->current_idx );
1263 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1264 (unsigned int)nreq->out.vector_count );
1265 print_req_vectors(nreq);
1269 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1270 * we need to sign/encrypt here with the last/first key we remembered
1272 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1273 status = smb2_signing_encrypt_pdu(req->first_key,
1274 xconn->smb2.server.cipher,
1275 firsttf,
1276 nreq->out.vector_count - first_idx);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 return status;
1280 } else if (req->last_key.length > 0) {
1281 status = smb2_signing_sign_pdu(req->last_key,
1282 xconn->protocol,
1283 outhdr_v,
1284 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 return status;
1290 nreq->queue_entry.mem_ctx = nreq;
1291 nreq->queue_entry.vector = nreq->out.vector;
1292 nreq->queue_entry.count = nreq->out.vector_count;
1293 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1294 xconn->smb2.send_queue_len++;
1296 status = smbd_smb2_flush_send_queue(xconn);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 return status;
1301 return NT_STATUS_OK;
1304 struct smbd_smb2_request_pending_state {
1305 struct smbd_smb2_send_queue queue_entry;
1306 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1307 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1310 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1311 struct tevent_timer *te,
1312 struct timeval current_time,
1313 void *private_data);
1315 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1316 struct tevent_req *subreq,
1317 uint32_t defer_time)
1319 NTSTATUS status;
1320 struct timeval defer_endtime;
1321 uint8_t *outhdr = NULL;
1322 uint32_t flags;
1324 if (!tevent_req_is_in_progress(subreq)) {
1326 * This is a performance optimization,
1327 * it avoids one tevent_loop iteration,
1328 * which means we avoid one
1329 * talloc_stackframe_pool/talloc_free pair.
1331 tevent_req_notify_callback(subreq);
1332 return NT_STATUS_OK;
1335 req->subreq = subreq;
1336 subreq = NULL;
1338 if (req->async_te) {
1339 /* We're already async. */
1340 return NT_STATUS_OK;
1343 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1344 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1345 if (flags & SMB2_HDR_FLAG_ASYNC) {
1346 /* We're already async. */
1347 return NT_STATUS_OK;
1350 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1352 * We're trying to go async in a compound request
1353 * chain. This is only allowed for opens that cause an
1354 * oplock break or for the last operation in the
1355 * chain, otherwise it is not allowed. See
1356 * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
1358 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1360 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1362 * Cancel the outstanding request.
1364 bool ok = tevent_req_cancel(req->subreq);
1365 if (ok) {
1366 return NT_STATUS_OK;
1368 TALLOC_FREE(req->subreq);
1369 return smbd_smb2_request_error(req,
1370 NT_STATUS_INTERNAL_ERROR);
1374 if (DEBUGLEVEL >= 10) {
1375 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1376 (unsigned int)req->current_idx );
1377 print_req_vectors(req);
1380 if (req->current_idx > 1) {
1382 * We're going async in a compound
1383 * chain after the first request has
1384 * already been processed. Send an
1385 * interim response containing the
1386 * set of replies already generated.
1388 int idx = req->current_idx;
1390 status = smb2_send_async_interim_response(req);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 return status;
1394 if (req->first_key.length > 0) {
1395 data_blob_clear_free(&req->first_key);
1398 req->current_idx = 1;
1401 * Re-arrange the in.vectors to remove what
1402 * we just sent.
1404 memmove(&req->in.vector[1],
1405 &req->in.vector[idx],
1406 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1407 req->in.vector_count = 1 + (req->in.vector_count - idx);
1409 /* Re-arrange the out.vectors to match. */
1410 memmove(&req->out.vector[1],
1411 &req->out.vector[idx],
1412 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1413 req->out.vector_count = 1 + (req->out.vector_count - idx);
1415 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1417 * We only have one remaining request as
1418 * we've processed everything else.
1419 * This is no longer a compound request.
1421 req->compound_related = false;
1422 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1423 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1424 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1427 if (req->last_key.length > 0) {
1428 data_blob_clear_free(&req->last_key);
1431 defer_endtime = timeval_current_ofs_usec(defer_time);
1432 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1433 req, defer_endtime,
1434 smbd_smb2_request_pending_timer,
1435 req);
1436 if (req->async_te == NULL) {
1437 return NT_STATUS_NO_MEMORY;
1440 return NT_STATUS_OK;
1443 static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
1444 struct smbXsrv_connection *xconn)
1446 struct smbXsrv_channel_global0 *c = NULL;
1447 NTSTATUS status;
1448 DATA_BLOB key = data_blob_null;
1450 status = smbXsrv_session_find_channel(session, xconn, &c);
1451 if (NT_STATUS_IS_OK(status)) {
1452 key = c->signing_key;
1455 if (key.length == 0) {
1456 key = session->global->signing_key;
1459 return key;
1462 static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
1463 uint64_t *new_nonce_high,
1464 uint64_t *new_nonce_low)
1466 uint64_t nonce_high;
1467 uint64_t nonce_low;
1469 session->nonce_low += 1;
1470 if (session->nonce_low == 0) {
1471 session->nonce_low += 1;
1472 session->nonce_high += 1;
1476 * CCM and GCM algorithms must never have their
1477 * nonce wrap, or the security of the whole
1478 * communication and the keys is destroyed.
1479 * We must drop the connection once we have
1480 * transfered too much data.
1482 * NOTE: We assume nonces greater than 8 bytes.
1484 if (session->nonce_high >= session->nonce_high_max) {
1485 return NT_STATUS_ENCRYPTION_FAILED;
1488 nonce_high = session->nonce_high_random;
1489 nonce_high += session->nonce_high;
1490 nonce_low = session->nonce_low;
1492 *new_nonce_high = nonce_high;
1493 *new_nonce_low = nonce_low;
1494 return NT_STATUS_OK;
1497 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1498 struct tevent_timer *te,
1499 struct timeval current_time,
1500 void *private_data)
1502 struct smbd_smb2_request *req =
1503 talloc_get_type_abort(private_data,
1504 struct smbd_smb2_request);
1505 struct smbXsrv_connection *xconn = req->xconn;
1506 struct smbd_smb2_request_pending_state *state = NULL;
1507 uint8_t *outhdr = NULL;
1508 const uint8_t *inhdr = NULL;
1509 uint8_t *tf = NULL;
1510 size_t tf_len = 0;
1511 uint8_t *hdr = NULL;
1512 uint8_t *body = NULL;
1513 uint8_t *dyn = NULL;
1514 uint32_t flags = 0;
1515 uint64_t session_id = 0;
1516 uint64_t message_id = 0;
1517 uint64_t nonce_high = 0;
1518 uint64_t nonce_low = 0;
1519 uint64_t async_id = 0;
1520 NTSTATUS status;
1521 bool ok;
1523 TALLOC_FREE(req->async_te);
1525 /* Ensure our final reply matches the interim one. */
1526 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1527 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1528 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1529 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1530 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1532 async_id = message_id; /* keep it simple for now... */
1534 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1535 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1537 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1538 "going async\n",
1539 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1540 (unsigned long long)async_id ));
1543 * What we send is identical to a smbd_smb2_request_error
1544 * packet with an error status of STATUS_PENDING. Make use
1545 * of this fact sometime when refactoring. JRA.
1548 state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
1549 if (state == NULL) {
1550 smbd_server_connection_terminate(xconn,
1551 nt_errstr(NT_STATUS_NO_MEMORY));
1552 return;
1555 tf = state->buf + NBT_HDR_SIZE;
1556 tf_len = SMB2_TF_HDR_SIZE;
1558 hdr = tf + SMB2_TF_HDR_SIZE;
1559 body = hdr + SMB2_HDR_BODY;
1560 dyn = body + 8;
1562 if (req->do_encryption) {
1563 status = smb2_get_new_nonce(req->session,
1564 &nonce_high,
1565 &nonce_low);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 smbd_server_connection_terminate(xconn,
1568 nt_errstr(status));
1569 return;
1573 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1574 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1575 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1576 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1578 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1579 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1580 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1581 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1582 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1584 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1585 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1586 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1587 SBVAL(hdr, SMB2_HDR_PID, async_id);
1588 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1589 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1590 memcpy(hdr+SMB2_HDR_SIGNATURE,
1591 outhdr+SMB2_HDR_SIGNATURE, 16);
1593 SSVAL(body, 0x00, 0x08 + 1);
1595 SCVAL(body, 0x02, 0);
1596 SCVAL(body, 0x03, 0);
1597 SIVAL(body, 0x04, 0);
1598 /* Match W2K8R2... */
1599 SCVAL(dyn, 0x00, 0x21);
1601 state->vector[0].iov_base = (void *)state->buf;
1602 state->vector[0].iov_len = NBT_HDR_SIZE;
1604 if (req->do_encryption) {
1605 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1606 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1607 } else {
1608 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1609 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1612 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1613 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1615 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1616 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1618 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1619 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1621 ok = smb2_setup_nbt_length(state->vector,
1622 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1623 if (!ok) {
1624 smbd_server_connection_terminate(
1625 xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
1626 return;
1629 /* Ensure we correctly go through crediting. Grant
1630 the credits now, and zero credits on the final
1631 response. */
1632 smb2_set_operation_credit(req->xconn,
1633 SMBD_SMB2_IN_HDR_IOV(req),
1634 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1636 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1638 if (DEBUGLVL(10)) {
1639 int i;
1641 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1642 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1643 (unsigned int)i,
1644 (unsigned int)ARRAY_SIZE(state->vector),
1645 (unsigned int)state->vector[i].iov_len);
1649 if (req->do_encryption) {
1650 struct smbXsrv_session *x = req->session;
1651 DATA_BLOB encryption_key = x->global->encryption_key;
1653 status = smb2_signing_encrypt_pdu(encryption_key,
1654 xconn->smb2.server.cipher,
1655 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1656 SMBD_SMB2_NUM_IOV_PER_REQ);
1657 if (!NT_STATUS_IS_OK(status)) {
1658 smbd_server_connection_terminate(xconn,
1659 nt_errstr(status));
1660 return;
1662 } else if (req->do_signing) {
1663 struct smbXsrv_session *x = req->session;
1664 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
1666 status = smb2_signing_sign_pdu(signing_key,
1667 xconn->protocol,
1668 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1669 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1670 if (!NT_STATUS_IS_OK(status)) {
1671 smbd_server_connection_terminate(xconn,
1672 nt_errstr(status));
1673 return;
1677 state->queue_entry.mem_ctx = state;
1678 state->queue_entry.vector = state->vector;
1679 state->queue_entry.count = ARRAY_SIZE(state->vector);
1680 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1681 xconn->smb2.send_queue_len++;
1683 status = smbd_smb2_flush_send_queue(xconn);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 smbd_server_connection_terminate(xconn,
1686 nt_errstr(status));
1687 return;
1691 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1693 struct smbXsrv_connection *xconn = req->xconn;
1694 struct smbd_smb2_request *cur;
1695 const uint8_t *inhdr;
1696 uint32_t flags;
1697 uint64_t search_message_id;
1698 uint64_t search_async_id;
1699 uint64_t found_id;
1701 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1703 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1704 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1705 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1708 * we don't need the request anymore
1709 * cancel requests never have a response
1711 DLIST_REMOVE(xconn->smb2.requests, req);
1712 TALLOC_FREE(req);
1714 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1715 const uint8_t *outhdr;
1716 uint64_t message_id;
1717 uint64_t async_id;
1719 if (cur->compound_related) {
1721 * Never cancel anything in a compound request.
1722 * Way too hard to deal with the result.
1724 continue;
1727 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1729 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1730 async_id = BVAL(outhdr, SMB2_HDR_PID);
1732 if (flags & SMB2_HDR_FLAG_ASYNC) {
1733 if (search_async_id == async_id) {
1734 found_id = async_id;
1735 break;
1737 } else {
1738 if (search_message_id == message_id) {
1739 found_id = message_id;
1740 break;
1745 if (cur && cur->subreq) {
1746 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1747 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1748 "cancel opcode[%s] mid %llu\n",
1749 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1750 (unsigned long long)found_id ));
1751 tevent_req_cancel(cur->subreq);
1754 return NT_STATUS_OK;
1757 /*************************************************************
1758 Ensure an incoming tid is a valid one for us to access.
1759 Change to the associated uid credentials and chdir to the
1760 valid tid directory.
1761 *************************************************************/
1763 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1765 const uint8_t *inhdr;
1766 uint32_t in_flags;
1767 uint32_t in_tid;
1768 struct smbXsrv_tcon *tcon;
1769 NTSTATUS status;
1770 NTTIME now = timeval_to_nttime(&req->request_time);
1772 req->tcon = NULL;
1774 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1776 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1777 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1779 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1780 in_tid = req->last_tid;
1783 req->last_tid = 0;
1785 status = smb2srv_tcon_lookup(req->session,
1786 in_tid, now, &tcon);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 return status;
1791 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1792 return NT_STATUS_ACCESS_DENIED;
1795 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1796 if (!set_current_service(tcon->compat, 0, true)) {
1797 return NT_STATUS_ACCESS_DENIED;
1800 req->tcon = tcon;
1801 req->last_tid = in_tid;
1803 return NT_STATUS_OK;
1806 /*************************************************************
1807 Ensure an incoming session_id is a valid one for us to access.
1808 *************************************************************/
1810 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1812 const uint8_t *inhdr;
1813 uint32_t in_flags;
1814 uint16_t in_opcode;
1815 uint64_t in_session_id;
1816 struct smbXsrv_session *session = NULL;
1817 struct auth_session_info *session_info;
1818 NTSTATUS status;
1819 NTTIME now = timeval_to_nttime(&req->request_time);
1821 req->session = NULL;
1822 req->tcon = NULL;
1824 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1826 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1827 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1828 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1830 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1831 in_session_id = req->last_session_id;
1834 req->last_session_id = 0;
1836 /* look an existing session up */
1837 switch (in_opcode) {
1838 case SMB2_OP_SESSSETUP:
1840 * For a session bind request, we don't have the
1841 * channel set up at this point yet, so we defer
1842 * the verification that the connection belongs
1843 * to the session to the session setup code, which
1844 * can look at the session binding flags.
1846 status = smb2srv_session_lookup_client(req->xconn->client,
1847 in_session_id, now,
1848 &session);
1849 break;
1850 default:
1851 status = smb2srv_session_lookup_conn(req->xconn,
1852 in_session_id, now,
1853 &session);
1854 break;
1856 if (session) {
1857 req->session = session;
1858 req->last_session_id = in_session_id;
1860 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1861 switch (in_opcode) {
1862 case SMB2_OP_SESSSETUP:
1863 status = NT_STATUS_OK;
1864 break;
1865 default:
1866 break;
1869 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1870 switch (in_opcode) {
1871 case SMB2_OP_TCON:
1872 case SMB2_OP_CREATE:
1873 case SMB2_OP_GETINFO:
1874 case SMB2_OP_SETINFO:
1875 return NT_STATUS_INVALID_HANDLE;
1876 default:
1878 * Notice the check for
1879 * (session_info == NULL)
1880 * below.
1882 status = NT_STATUS_OK;
1883 break;
1886 if (!NT_STATUS_IS_OK(status)) {
1887 return status;
1890 session_info = session->global->auth_session_info;
1891 if (session_info == NULL) {
1892 return NT_STATUS_INVALID_HANDLE;
1895 if (in_session_id != req->xconn->client->last_session_id) {
1896 req->xconn->client->last_session_id = in_session_id;
1897 set_current_user_info(session_info->unix_info->sanitized_username,
1898 session_info->unix_info->unix_name,
1899 session_info->info->domain_name);
1902 return NT_STATUS_OK;
1905 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1906 uint32_t data_length)
1908 struct smbXsrv_connection *xconn = req->xconn;
1909 uint16_t needed_charge;
1910 uint16_t credit_charge = 1;
1911 const uint8_t *inhdr;
1913 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1915 if (xconn->smb2.credits.multicredit) {
1916 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1917 credit_charge = MAX(credit_charge, 1);
1920 needed_charge = (data_length - 1)/ 65536 + 1;
1922 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1923 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1924 credit_charge, needed_charge));
1926 if (needed_charge > credit_charge) {
1927 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1928 credit_charge, needed_charge));
1929 return NT_STATUS_INVALID_PARAMETER;
1932 return NT_STATUS_OK;
1935 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1936 size_t expected_body_size)
1938 struct iovec *inhdr_v;
1939 const uint8_t *inhdr;
1940 uint16_t opcode;
1941 const uint8_t *inbody;
1942 size_t body_size;
1943 size_t min_dyn_size = expected_body_size & 0x00000001;
1944 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1947 * The following should be checked already.
1949 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1950 return NT_STATUS_INTERNAL_ERROR;
1952 if (req->current_idx > max_idx) {
1953 return NT_STATUS_INTERNAL_ERROR;
1956 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1957 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1958 return NT_STATUS_INTERNAL_ERROR;
1960 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1961 return NT_STATUS_INTERNAL_ERROR;
1964 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1965 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1967 switch (opcode) {
1968 case SMB2_OP_IOCTL:
1969 case SMB2_OP_GETINFO:
1970 min_dyn_size = 0;
1971 break;
1972 case SMB2_OP_WRITE:
1973 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1974 if (req->smb1req->unread_bytes < min_dyn_size) {
1975 return NT_STATUS_INVALID_PARAMETER;
1978 min_dyn_size = 0;
1980 break;
1984 * Now check the expected body size,
1985 * where the last byte might be in the
1986 * dynamic section..
1988 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1989 return NT_STATUS_INVALID_PARAMETER;
1991 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1992 return NT_STATUS_INVALID_PARAMETER;
1995 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1997 body_size = SVAL(inbody, 0x00);
1998 if (body_size != expected_body_size) {
1999 return NT_STATUS_INVALID_PARAMETER;
2002 return NT_STATUS_OK;
2005 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2007 struct smbXsrv_connection *xconn = req->xconn;
2008 const struct smbd_smb2_dispatch_table *call = NULL;
2009 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2010 const uint8_t *inhdr;
2011 uint16_t opcode;
2012 uint32_t flags;
2013 uint64_t mid;
2014 NTSTATUS status;
2015 NTSTATUS session_status;
2016 uint32_t allowed_flags;
2017 NTSTATUS return_value;
2018 struct smbXsrv_session *x = NULL;
2019 bool signing_required = false;
2020 bool encryption_desired = false;
2021 bool encryption_required = false;
2023 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2025 DO_PROFILE_INC(request);
2027 /* TODO: verify more things */
2029 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2030 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2031 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2032 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
2033 smb2_opcode_name(opcode),
2034 (unsigned long long)mid));
2036 if (xconn->protocol >= PROTOCOL_SMB2_02) {
2038 * once the protocol is negotiated
2039 * SMB2_OP_NEGPROT is not allowed anymore
2041 if (opcode == SMB2_OP_NEGPROT) {
2042 /* drop the connection */
2043 return NT_STATUS_INVALID_PARAMETER;
2045 } else {
2047 * if the protocol is not negotiated yet
2048 * only SMB2_OP_NEGPROT is allowed.
2050 if (opcode != SMB2_OP_NEGPROT) {
2051 /* drop the connection */
2052 return NT_STATUS_INVALID_PARAMETER;
2057 * Check if the client provided a valid session id,
2058 * if so smbd_smb2_request_check_session() calls
2059 * set_current_user_info().
2061 * As some command don't require a valid session id
2062 * we defer the check of the session_status
2064 session_status = smbd_smb2_request_check_session(req);
2065 x = req->session;
2066 if (x != NULL) {
2067 signing_required = x->global->signing_required;
2068 encryption_desired = x->encryption_desired;
2069 encryption_required = x->global->encryption_required;
2072 req->do_signing = false;
2073 req->do_encryption = false;
2074 req->was_encrypted = false;
2075 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
2076 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
2077 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
2079 if (x != NULL && x->global->session_wire_id != tf_session_id) {
2080 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
2081 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
2082 (unsigned long long)x->global->session_wire_id,
2083 (unsigned long long)tf_session_id));
2085 * TODO: windows allows this...
2086 * should we drop the connection?
2088 * For now we just return ACCESS_DENIED
2089 * (Windows clients never trigger this)
2090 * and wait for an update of [MS-SMB2].
2092 return smbd_smb2_request_error(req,
2093 NT_STATUS_ACCESS_DENIED);
2096 req->was_encrypted = true;
2099 if (encryption_required && !req->was_encrypted) {
2100 return smbd_smb2_request_error(req,
2101 NT_STATUS_ACCESS_DENIED);
2104 call = smbd_smb2_call(opcode);
2105 if (call == NULL) {
2106 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2109 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2110 SMB2_HDR_FLAG_SIGNED |
2111 SMB2_HDR_FLAG_DFS;
2112 if (xconn->protocol >= PROTOCOL_SMB3_11) {
2113 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2115 if (opcode == SMB2_OP_NEGPROT) {
2116 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
2117 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
2120 if (opcode == SMB2_OP_CANCEL) {
2121 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2123 if ((flags & ~allowed_flags) != 0) {
2124 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2127 if (flags & SMB2_HDR_FLAG_CHAINED) {
2129 * This check is mostly for giving the correct error code
2130 * for compounded requests.
2132 if (!NT_STATUS_IS_OK(session_status)) {
2133 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2135 } else {
2136 req->compat_chain_fsp = NULL;
2139 if (req->was_encrypted) {
2140 signing_required = false;
2141 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2142 DATA_BLOB signing_key = data_blob_null;
2144 if (x == NULL) {
2146 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2147 * If the SMB2 header of the SMB2 NEGOTIATE
2148 * request has the SMB2_FLAGS_SIGNED bit set in the
2149 * Flags field, the server MUST fail the request
2150 * with STATUS_INVALID_PARAMETER.
2152 * Microsoft test tool checks this.
2155 if ((opcode == SMB2_OP_NEGPROT) &&
2156 (flags & SMB2_HDR_FLAG_SIGNED)) {
2157 status = NT_STATUS_INVALID_PARAMETER;
2158 } else {
2159 status = NT_STATUS_USER_SESSION_DELETED;
2161 return smbd_smb2_request_error(req, status);
2164 signing_key = smbd_smb2_signing_key(x, xconn);
2167 * If we have a signing key, we should
2168 * sign the response
2170 if (signing_key.length > 0) {
2171 req->do_signing = true;
2174 status = smb2_signing_check_pdu(signing_key,
2175 xconn->protocol,
2176 SMBD_SMB2_IN_HDR_IOV(req),
2177 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 return smbd_smb2_request_error(req, status);
2183 * Now that we know the request was correctly signed
2184 * we have to sign the response too.
2186 req->do_signing = true;
2188 if (!NT_STATUS_IS_OK(session_status)) {
2189 return smbd_smb2_request_error(req, session_status);
2191 } else if (opcode == SMB2_OP_CANCEL) {
2192 /* Cancel requests are allowed to skip the signing */
2193 } else if (signing_required) {
2195 * If signing is required we try to sign
2196 * a possible error response
2198 req->do_signing = true;
2199 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2202 if (flags & SMB2_HDR_FLAG_CHAINED) {
2203 req->compound_related = true;
2206 if (call->need_session) {
2207 if (!NT_STATUS_IS_OK(session_status)) {
2208 return smbd_smb2_request_error(req, session_status);
2212 if (call->need_tcon) {
2213 SMB_ASSERT(call->need_session);
2216 * This call needs to be run as user.
2218 * smbd_smb2_request_check_tcon()
2219 * calls change_to_user() on success.
2221 status = smbd_smb2_request_check_tcon(req);
2222 if (!NT_STATUS_IS_OK(status)) {
2223 return smbd_smb2_request_error(req, status);
2225 if (req->tcon->encryption_desired) {
2226 encryption_desired = true;
2228 if (req->tcon->global->encryption_required) {
2229 encryption_required = true;
2231 if (encryption_required && !req->was_encrypted) {
2232 return smbd_smb2_request_error(req,
2233 NT_STATUS_ACCESS_DENIED);
2237 if (req->was_encrypted || encryption_desired) {
2238 req->do_encryption = true;
2241 if (call->fileid_ofs != 0) {
2242 size_t needed = call->fileid_ofs + 16;
2243 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2244 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2245 uint64_t file_id_persistent;
2246 uint64_t file_id_volatile;
2247 struct files_struct *fsp;
2249 SMB_ASSERT(call->need_tcon);
2251 if (needed > body_size) {
2252 return smbd_smb2_request_error(req,
2253 NT_STATUS_INVALID_PARAMETER);
2256 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2257 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2259 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2260 if (fsp == NULL) {
2261 if (!call->allow_invalid_fileid) {
2262 return smbd_smb2_request_error(req,
2263 NT_STATUS_FILE_CLOSED);
2266 if (file_id_persistent != UINT64_MAX) {
2267 return smbd_smb2_request_error(req,
2268 NT_STATUS_FILE_CLOSED);
2270 if (file_id_volatile != UINT64_MAX) {
2271 return smbd_smb2_request_error(req,
2272 NT_STATUS_FILE_CLOSED);
2277 if (call->as_root) {
2278 SMB_ASSERT(call->fileid_ofs == 0);
2279 /* This call needs to be run as root */
2280 change_to_root_user();
2281 } else {
2282 SMB_ASSERT(call->need_tcon);
2285 #define _INBYTES(_r) \
2286 iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
2288 switch (opcode) {
2289 case SMB2_OP_NEGPROT:
2290 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
2291 req->profile, _INBYTES(req));
2292 return_value = smbd_smb2_request_process_negprot(req);
2293 break;
2295 case SMB2_OP_SESSSETUP:
2296 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
2297 req->profile, _INBYTES(req));
2298 return_value = smbd_smb2_request_process_sesssetup(req);
2299 break;
2301 case SMB2_OP_LOGOFF:
2302 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
2303 req->profile, _INBYTES(req));
2304 return_value = smbd_smb2_request_process_logoff(req);
2305 break;
2307 case SMB2_OP_TCON:
2308 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
2309 req->profile, _INBYTES(req));
2310 return_value = smbd_smb2_request_process_tcon(req);
2311 break;
2313 case SMB2_OP_TDIS:
2314 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
2315 req->profile, _INBYTES(req));
2316 return_value = smbd_smb2_request_process_tdis(req);
2317 break;
2319 case SMB2_OP_CREATE:
2320 if (req->subreq == NULL) {
2321 SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
2322 req->profile, _INBYTES(req));
2323 } else {
2324 SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
2326 return_value = smbd_smb2_request_process_create(req);
2327 break;
2329 case SMB2_OP_CLOSE:
2330 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
2331 req->profile, _INBYTES(req));
2332 return_value = smbd_smb2_request_process_close(req);
2333 break;
2335 case SMB2_OP_FLUSH:
2336 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
2337 req->profile, _INBYTES(req));
2338 return_value = smbd_smb2_request_process_flush(req);
2339 break;
2341 case SMB2_OP_READ:
2342 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
2343 req->profile, _INBYTES(req));
2344 return_value = smbd_smb2_request_process_read(req);
2345 break;
2347 case SMB2_OP_WRITE:
2348 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
2349 req->profile, _INBYTES(req));
2350 return_value = smbd_smb2_request_process_write(req);
2351 break;
2353 case SMB2_OP_LOCK:
2354 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
2355 req->profile, _INBYTES(req));
2356 return_value = smbd_smb2_request_process_lock(req);
2357 break;
2359 case SMB2_OP_IOCTL:
2360 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
2361 req->profile, _INBYTES(req));
2362 return_value = smbd_smb2_request_process_ioctl(req);
2363 break;
2365 case SMB2_OP_CANCEL:
2366 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
2367 req->profile, _INBYTES(req));
2368 return_value = smbd_smb2_request_process_cancel(req);
2369 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
2370 break;
2372 case SMB2_OP_KEEPALIVE:
2373 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
2374 req->profile, _INBYTES(req));
2375 return_value = smbd_smb2_request_process_keepalive(req);
2376 break;
2378 case SMB2_OP_QUERY_DIRECTORY:
2379 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
2380 req->profile, _INBYTES(req));
2381 return_value = smbd_smb2_request_process_query_directory(req);
2382 break;
2384 case SMB2_OP_NOTIFY:
2385 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
2386 req->profile, _INBYTES(req));
2387 return_value = smbd_smb2_request_process_notify(req);
2388 break;
2390 case SMB2_OP_GETINFO:
2391 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
2392 req->profile, _INBYTES(req));
2393 return_value = smbd_smb2_request_process_getinfo(req);
2394 break;
2396 case SMB2_OP_SETINFO:
2397 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
2398 req->profile, _INBYTES(req));
2399 return_value = smbd_smb2_request_process_setinfo(req);
2400 break;
2402 case SMB2_OP_BREAK:
2403 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
2404 req->profile, _INBYTES(req));
2405 return_value = smbd_smb2_request_process_break(req);
2406 break;
2408 default:
2409 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2410 break;
2412 return return_value;
2415 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2417 struct smbXsrv_connection *xconn = req->xconn;
2418 int first_idx = 1;
2419 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2420 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2421 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2422 NTSTATUS status;
2423 bool ok;
2425 req->subreq = NULL;
2426 TALLOC_FREE(req->async_te);
2428 if (req->do_encryption &&
2429 (firsttf->iov_len == 0) &&
2430 (req->first_key.length == 0) &&
2431 (req->session != NULL) &&
2432 (req->session->global->encryption_key.length != 0))
2434 DATA_BLOB encryption_key = req->session->global->encryption_key;
2435 uint8_t *tf;
2436 uint64_t session_id = req->session->global->session_wire_id;
2437 uint64_t nonce_high;
2438 uint64_t nonce_low;
2440 status = smb2_get_new_nonce(req->session,
2441 &nonce_high,
2442 &nonce_low);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 return status;
2448 * We need to place the SMB2_TRANSFORM header before the
2449 * first SMB2 header
2453 * we need to remember the encryption key
2454 * and defer the signing/encryption until
2455 * we are sure that we do not change
2456 * the header again.
2458 req->first_key = data_blob_dup_talloc(req, encryption_key);
2459 if (req->first_key.data == NULL) {
2460 return NT_STATUS_NO_MEMORY;
2463 tf = talloc_zero_array(req, uint8_t,
2464 SMB2_TF_HDR_SIZE);
2465 if (tf == NULL) {
2466 return NT_STATUS_NO_MEMORY;
2469 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2470 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2471 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2472 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2474 firsttf->iov_base = (void *)tf;
2475 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2478 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2479 (req->last_key.length > 0) &&
2480 (firsttf->iov_len == 0))
2482 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2483 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2486 * As we are sure the header of the last request in the
2487 * compound chain will not change, we can to sign here
2488 * with the last signing key we remembered.
2490 status = smb2_signing_sign_pdu(req->last_key,
2491 xconn->protocol,
2492 lasthdr,
2493 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 return status;
2498 if (req->last_key.length > 0) {
2499 data_blob_clear_free(&req->last_key);
2502 SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
2503 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
2505 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2507 if (req->current_idx < req->out.vector_count) {
2509 * We must process the remaining compound
2510 * SMB2 requests before any new incoming SMB2
2511 * requests. This is because incoming SMB2
2512 * requests may include a cancel for a
2513 * compound request we haven't processed
2514 * yet.
2516 struct tevent_immediate *im = tevent_create_immediate(req);
2517 if (!im) {
2518 return NT_STATUS_NO_MEMORY;
2521 if (req->do_signing && firsttf->iov_len == 0) {
2522 struct smbXsrv_session *x = req->session;
2523 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2526 * we need to remember the signing key
2527 * and defer the signing until
2528 * we are sure that we do not change
2529 * the header again.
2531 req->last_key = data_blob_dup_talloc(req, signing_key);
2532 if (req->last_key.data == NULL) {
2533 return NT_STATUS_NO_MEMORY;
2537 tevent_schedule_immediate(im,
2538 req->sconn->ev_ctx,
2539 smbd_smb2_request_dispatch_immediate,
2540 req);
2541 return NT_STATUS_OK;
2544 if (req->compound_related) {
2545 req->compound_related = false;
2548 ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2549 if (!ok) {
2550 return NT_STATUS_INVALID_PARAMETER_MIX;
2553 /* Set credit for these operations (zero credits if this
2554 is a final reply for an async operation). */
2555 smb2_calculate_credits(req, req);
2558 * now check if we need to sign the current response
2560 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2561 status = smb2_signing_encrypt_pdu(req->first_key,
2562 xconn->smb2.server.cipher,
2563 firsttf,
2564 req->out.vector_count - first_idx);
2565 if (!NT_STATUS_IS_OK(status)) {
2566 return status;
2568 } else if (req->do_signing) {
2569 struct smbXsrv_session *x = req->session;
2570 DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
2572 status = smb2_signing_sign_pdu(signing_key,
2573 xconn->protocol,
2574 outhdr,
2575 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 return status;
2580 if (req->first_key.length > 0) {
2581 data_blob_clear_free(&req->first_key);
2584 if (req->preauth != NULL) {
2585 struct hc_sha512state sctx;
2586 int i;
2588 samba_SHA512_Init(&sctx);
2589 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2590 sizeof(req->preauth->sha512_value));
2591 for (i = 1; i < req->in.vector_count; i++) {
2592 samba_SHA512_Update(&sctx,
2593 req->in.vector[i].iov_base,
2594 req->in.vector[i].iov_len);
2596 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2598 samba_SHA512_Init(&sctx);
2599 samba_SHA512_Update(&sctx, req->preauth->sha512_value,
2600 sizeof(req->preauth->sha512_value));
2601 for (i = 1; i < req->out.vector_count; i++) {
2602 samba_SHA512_Update(&sctx,
2603 req->out.vector[i].iov_base,
2604 req->out.vector[i].iov_len);
2606 samba_SHA512_Final(req->preauth->sha512_value, &sctx);
2608 req->preauth = NULL;
2611 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2612 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2613 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2614 /* Dynamic part is NULL. Chop it off,
2615 We're going to send it via sendfile. */
2616 req->out.vector_count -= 1;
2620 * We're done with this request -
2621 * move it off the "being processed" queue.
2623 DLIST_REMOVE(xconn->smb2.requests, req);
2625 req->queue_entry.mem_ctx = req;
2626 req->queue_entry.vector = req->out.vector;
2627 req->queue_entry.count = req->out.vector_count;
2628 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2629 xconn->smb2.send_queue_len++;
2631 status = smbd_smb2_flush_send_queue(xconn);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 return status;
2636 return NT_STATUS_OK;
2639 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
2641 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2642 struct tevent_immediate *im,
2643 void *private_data)
2645 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2646 struct smbd_smb2_request);
2647 struct smbXsrv_connection *xconn = req->xconn;
2648 NTSTATUS status;
2650 TALLOC_FREE(im);
2652 if (DEBUGLEVEL >= 10) {
2653 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2654 req->current_idx, req->in.vector_count));
2655 print_req_vectors(req);
2658 status = smbd_smb2_request_dispatch(req);
2659 if (!NT_STATUS_IS_OK(status)) {
2660 smbd_server_connection_terminate(xconn, nt_errstr(status));
2661 return;
2664 status = smbd_smb2_request_next_incoming(xconn);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 smbd_server_connection_terminate(xconn, nt_errstr(status));
2667 return;
2671 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2672 NTSTATUS status,
2673 DATA_BLOB body, DATA_BLOB *dyn,
2674 const char *location)
2676 uint8_t *outhdr;
2677 struct iovec *outbody_v;
2678 struct iovec *outdyn_v;
2679 uint32_t next_command_ofs;
2681 DEBUG(10,("smbd_smb2_request_done_ex: "
2682 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2683 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2684 dyn ? "yes": "no",
2685 (unsigned int)(dyn ? dyn->length : 0),
2686 location));
2688 if (body.length < 2) {
2689 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2692 if ((body.length % 2) != 0) {
2693 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2696 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2697 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2698 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2700 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2701 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2703 outbody_v->iov_base = (void *)body.data;
2704 outbody_v->iov_len = body.length;
2706 if (dyn) {
2707 outdyn_v->iov_base = (void *)dyn->data;
2708 outdyn_v->iov_len = dyn->length;
2709 } else {
2710 outdyn_v->iov_base = NULL;
2711 outdyn_v->iov_len = 0;
2715 * See if we need to recalculate the offset to the next response
2717 * Note that all responses may require padding (including the very last
2718 * one).
2720 if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
2721 next_command_ofs = SMB2_HDR_BODY;
2722 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2723 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2726 if ((next_command_ofs % 8) != 0) {
2727 size_t pad_size = 8 - (next_command_ofs % 8);
2728 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2730 * if the dyn buffer is empty
2731 * we can use it to add padding
2733 uint8_t *pad;
2735 pad = talloc_zero_array(req,
2736 uint8_t, pad_size);
2737 if (pad == NULL) {
2738 return smbd_smb2_request_error(req,
2739 NT_STATUS_NO_MEMORY);
2742 outdyn_v->iov_base = (void *)pad;
2743 outdyn_v->iov_len = pad_size;
2744 } else {
2746 * For now we copy the dynamic buffer
2747 * and add the padding to the new buffer
2749 size_t old_size;
2750 uint8_t *old_dyn;
2751 size_t new_size;
2752 uint8_t *new_dyn;
2754 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2755 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2757 new_size = old_size + pad_size;
2758 new_dyn = talloc_zero_array(req,
2759 uint8_t, new_size);
2760 if (new_dyn == NULL) {
2761 return smbd_smb2_request_error(req,
2762 NT_STATUS_NO_MEMORY);
2765 memcpy(new_dyn, old_dyn, old_size);
2766 memset(new_dyn + old_size, 0, pad_size);
2768 outdyn_v->iov_base = (void *)new_dyn;
2769 outdyn_v->iov_len = new_size;
2771 next_command_ofs += pad_size;
2774 if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
2775 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
2776 } else {
2777 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2779 return smbd_smb2_request_reply(req);
2782 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2783 NTSTATUS status,
2784 DATA_BLOB *info,
2785 const char *location)
2787 struct smbXsrv_connection *xconn = req->xconn;
2788 DATA_BLOB body;
2789 DATA_BLOB _dyn;
2790 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2791 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2793 DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
2794 "at %s\n", req->current_idx, nt_errstr(status),
2795 info ? " +info" : "", location);
2797 if (unread_bytes) {
2798 /* Recvfile error. Drain incoming socket. */
2799 size_t ret;
2801 errno = 0;
2802 ret = drain_socket(xconn->transport.sock, unread_bytes);
2803 if (ret != unread_bytes) {
2804 NTSTATUS error;
2806 if (errno == 0) {
2807 error = NT_STATUS_IO_DEVICE_ERROR;
2808 } else {
2809 error = map_nt_error_from_unix_common(errno);
2812 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2813 "ret[%u] errno[%d] => %s\n",
2814 (unsigned)unread_bytes,
2815 (unsigned)ret, errno, nt_errstr(error)));
2816 return error;
2820 body.data = outhdr + SMB2_HDR_BODY;
2821 body.length = 8;
2822 SSVAL(body.data, 0, 9);
2824 if (info) {
2825 SIVAL(body.data, 0x04, info->length);
2826 } else {
2827 /* Allocated size of req->out.vector[i].iov_base
2828 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2829 * 1 byte without having to do an alloc.
2831 info = &_dyn;
2832 info->data = ((uint8_t *)outhdr) +
2833 OUTVEC_ALLOC_SIZE - 1;
2834 info->length = 1;
2835 SCVAL(info->data, 0, 0);
2839 * Note: Even if there is an error, continue to process the request.
2840 * per MS-SMB2.
2843 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2847 struct smbd_smb2_send_break_state {
2848 struct smbd_smb2_send_queue queue_entry;
2849 uint8_t nbt_hdr[NBT_HDR_SIZE];
2850 uint8_t tf[SMB2_TF_HDR_SIZE];
2851 uint8_t hdr[SMB2_HDR_BODY];
2852 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2853 uint8_t body[1];
2856 static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
2857 struct smbXsrv_session *session,
2858 struct smbXsrv_tcon *tcon,
2859 const uint8_t *body,
2860 size_t body_len)
2862 struct smbd_smb2_send_break_state *state;
2863 bool do_encryption = false;
2864 uint64_t session_wire_id = 0;
2865 uint64_t nonce_high = 0;
2866 uint64_t nonce_low = 0;
2867 NTSTATUS status;
2868 size_t statelen;
2869 bool ok;
2871 if (session != NULL) {
2872 session_wire_id = session->global->session_wire_id;
2873 do_encryption = session->encryption_desired;
2874 if (tcon->encryption_desired) {
2875 do_encryption = true;
2879 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2880 body_len;
2882 state = talloc_zero_size(xconn, statelen);
2883 if (state == NULL) {
2884 return NT_STATUS_NO_MEMORY;
2886 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2888 if (do_encryption) {
2889 status = smb2_get_new_nonce(session,
2890 &nonce_high,
2891 &nonce_low);
2892 if (!NT_STATUS_IS_OK(status)) {
2893 return status;
2897 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2898 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2899 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2900 SBVAL(state->tf, SMB2_TF_SESSION_ID, session_wire_id);
2902 SIVAL(state->hdr, 0, SMB2_MAGIC);
2903 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2904 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2905 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2906 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2907 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2908 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2909 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2910 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2911 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2912 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2913 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2914 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2916 state->vector[0] = (struct iovec) {
2917 .iov_base = state->nbt_hdr,
2918 .iov_len = sizeof(state->nbt_hdr)
2921 if (do_encryption) {
2922 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2923 .iov_base = state->tf,
2924 .iov_len = sizeof(state->tf)
2926 } else {
2927 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2928 .iov_base = NULL,
2929 .iov_len = 0
2933 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2934 .iov_base = state->hdr,
2935 .iov_len = sizeof(state->hdr)
2938 memcpy(state->body, body, body_len);
2940 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2941 .iov_base = state->body,
2942 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2946 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2949 ok = smb2_setup_nbt_length(state->vector,
2950 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2951 if (!ok) {
2952 return NT_STATUS_INVALID_PARAMETER_MIX;
2955 if (do_encryption) {
2956 DATA_BLOB encryption_key = session->global->encryption_key;
2958 status = smb2_signing_encrypt_pdu(encryption_key,
2959 xconn->smb2.server.cipher,
2960 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2961 SMBD_SMB2_NUM_IOV_PER_REQ);
2962 if (!NT_STATUS_IS_OK(status)) {
2963 return status;
2967 state->queue_entry.mem_ctx = state;
2968 state->queue_entry.vector = state->vector;
2969 state->queue_entry.count = ARRAY_SIZE(state->vector);
2970 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2971 xconn->smb2.send_queue_len++;
2973 status = smbd_smb2_flush_send_queue(xconn);
2974 if (!NT_STATUS_IS_OK(status)) {
2975 return status;
2978 return NT_STATUS_OK;
2981 NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_connection *xconn,
2982 struct smbXsrv_session *session,
2983 struct smbXsrv_tcon *tcon,
2984 struct smbXsrv_open *op,
2985 uint8_t oplock_level)
2987 uint8_t body[0x18];
2989 SSVAL(body, 0x00, sizeof(body));
2990 SCVAL(body, 0x02, oplock_level);
2991 SCVAL(body, 0x03, 0); /* reserved */
2992 SIVAL(body, 0x04, 0); /* reserved */
2993 SBVAL(body, 0x08, op->global->open_persistent_id);
2994 SBVAL(body, 0x10, op->global->open_volatile_id);
2996 return smbd_smb2_send_break(xconn, session, tcon, body, sizeof(body));
2999 NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_connection *xconn,
3000 uint16_t new_epoch,
3001 uint32_t lease_flags,
3002 struct smb2_lease_key *lease_key,
3003 uint32_t current_lease_state,
3004 uint32_t new_lease_state)
3006 uint8_t body[0x2c];
3008 SSVAL(body, 0x00, sizeof(body));
3009 SSVAL(body, 0x02, new_epoch);
3010 SIVAL(body, 0x04, lease_flags);
3011 SBVAL(body, 0x08, lease_key->data[0]);
3012 SBVAL(body, 0x10, lease_key->data[1]);
3013 SIVAL(body, 0x18, current_lease_state);
3014 SIVAL(body, 0x1c, new_lease_state);
3015 SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
3016 SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
3017 SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
3019 return smbd_smb2_send_break(xconn, NULL, NULL, body, sizeof(body));
3022 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
3024 NTSTATUS status;
3025 uint32_t flags;
3026 uint64_t file_id_persistent;
3027 uint64_t file_id_volatile;
3028 struct smbXsrv_open *op = NULL;
3029 struct files_struct *fsp = NULL;
3030 const uint8_t *body = NULL;
3033 * This is only called with a pktbuf
3034 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
3035 * bytes
3038 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
3039 /* Transform header. Cannot recvfile. */
3040 return false;
3042 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
3043 /* Not SMB2. Normal error path will cope. */
3044 return false;
3046 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
3047 /* Not SMB2. Normal error path will cope. */
3048 return false;
3050 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
3051 /* Needs to be a WRITE. */
3052 return false;
3054 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
3055 /* Chained. Cannot recvfile. */
3056 return false;
3058 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
3059 if (flags & SMB2_HDR_FLAG_CHAINED) {
3060 /* Chained. Cannot recvfile. */
3061 return false;
3063 if (flags & SMB2_HDR_FLAG_SIGNED) {
3064 /* Signed. Cannot recvfile. */
3065 return false;
3068 body = &state->pktbuf[SMB2_HDR_BODY];
3070 file_id_persistent = BVAL(body, 0x10);
3071 file_id_volatile = BVAL(body, 0x18);
3073 status = smb2srv_open_lookup(state->req->xconn,
3074 file_id_persistent,
3075 file_id_volatile,
3076 0, /* now */
3077 &op);
3078 if (!NT_STATUS_IS_OK(status)) {
3079 return false;
3082 fsp = op->compat;
3083 if (fsp == NULL) {
3084 return false;
3086 if (fsp->conn == NULL) {
3087 return false;
3090 if (IS_IPC(fsp->conn)) {
3091 return false;
3093 if (IS_PRINT(fsp->conn)) {
3094 return false;
3097 DEBUG(10,("Doing recvfile write len = %u\n",
3098 (unsigned int)(state->pktfull - state->pktlen)));
3100 return true;
3103 static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
3105 struct smbd_server_connection *sconn = xconn->client->sconn;
3106 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3107 size_t max_send_queue_len;
3108 size_t cur_send_queue_len;
3110 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3112 * we're not supposed to do any io
3114 return NT_STATUS_OK;
3117 if (state->req != NULL) {
3119 * if there is already a tstream_readv_pdu
3120 * pending, we are done.
3122 return NT_STATUS_OK;
3125 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
3126 cur_send_queue_len = xconn->smb2.send_queue_len;
3128 if (cur_send_queue_len > max_send_queue_len) {
3130 * if we have a lot of requests to send,
3131 * we wait until they are on the wire until we
3132 * ask for the next request.
3134 return NT_STATUS_OK;
3137 /* ask for the next request */
3138 ZERO_STRUCTP(state);
3139 state->req = smbd_smb2_request_allocate(xconn);
3140 if (state->req == NULL) {
3141 return NT_STATUS_NO_MEMORY;
3143 state->req->sconn = sconn;
3144 state->req->xconn = xconn;
3145 state->min_recv_size = lp_min_receive_file_size();
3147 TEVENT_FD_READABLE(xconn->transport.fde);
3149 return NT_STATUS_OK;
3152 void smbd_smb2_first_negprot(struct smbXsrv_connection *xconn,
3153 const uint8_t *inpdu, size_t size)
3155 struct smbd_server_connection *sconn = xconn->client->sconn;
3156 NTSTATUS status;
3157 struct smbd_smb2_request *req = NULL;
3159 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3160 (unsigned int)size));
3162 status = smbd_initialize_smb2(xconn);
3163 if (!NT_STATUS_IS_OK(status)) {
3164 smbd_server_connection_terminate(xconn, nt_errstr(status));
3165 return;
3168 status = smbd_smb2_request_create(xconn, inpdu, size, &req);
3169 if (!NT_STATUS_IS_OK(status)) {
3170 smbd_server_connection_terminate(xconn, nt_errstr(status));
3171 return;
3174 status = smbd_smb2_request_validate(req);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 smbd_server_connection_terminate(xconn, nt_errstr(status));
3177 return;
3180 status = smbd_smb2_request_setup_out(req);
3181 if (!NT_STATUS_IS_OK(status)) {
3182 smbd_server_connection_terminate(xconn, nt_errstr(status));
3183 return;
3186 #ifdef WITH_PROFILE
3188 * this was already counted at the SMB1 layer =>
3189 * smbd_smb2_request_dispatch() should not count it twice.
3191 if (profile_p->values.request_stats.count > 0) {
3192 profile_p->values.request_stats.count--;
3194 #endif
3195 status = smbd_smb2_request_dispatch(req);
3196 if (!NT_STATUS_IS_OK(status)) {
3197 smbd_server_connection_terminate(xconn, nt_errstr(status));
3198 return;
3201 status = smbd_smb2_request_next_incoming(xconn);
3202 if (!NT_STATUS_IS_OK(status)) {
3203 smbd_server_connection_terminate(xconn, nt_errstr(status));
3204 return;
3207 sconn->num_requests++;
3210 static int socket_error_from_errno(int ret,
3211 int sys_errno,
3212 bool *retry)
3214 *retry = false;
3216 if (ret >= 0) {
3217 return 0;
3220 if (ret != -1) {
3221 return EIO;
3224 if (sys_errno == 0) {
3225 return EIO;
3228 if (sys_errno == EINTR) {
3229 *retry = true;
3230 return sys_errno;
3233 if (sys_errno == EINPROGRESS) {
3234 *retry = true;
3235 return sys_errno;
3238 if (sys_errno == EAGAIN) {
3239 *retry = true;
3240 return sys_errno;
3243 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3244 if (sys_errno == ENOMEM) {
3245 *retry = true;
3246 return sys_errno;
3249 #ifdef EWOULDBLOCK
3250 #if EWOULDBLOCK != EAGAIN
3251 if (sys_errno == EWOULDBLOCK) {
3252 *retry = true;
3253 return sys_errno;
3255 #endif
3256 #endif
3258 return sys_errno;
3261 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3263 int ret;
3264 int err;
3265 bool retry;
3267 if (xconn->smb2.send_queue == NULL) {
3268 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3269 return NT_STATUS_OK;
3272 while (xconn->smb2.send_queue != NULL) {
3273 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3274 bool ok;
3276 if (e->sendfile_header != NULL) {
3277 NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
3278 size_t size = 0;
3279 size_t i = 0;
3280 uint8_t *buf;
3282 for (i=0; i < e->count; i++) {
3283 size += e->vector[i].iov_len;
3286 if (size <= e->sendfile_header->length) {
3287 buf = e->sendfile_header->data;
3288 } else {
3289 buf = talloc_array(e->mem_ctx, uint8_t, size);
3290 if (buf == NULL) {
3291 return NT_STATUS_NO_MEMORY;
3295 size = 0;
3296 for (i=0; i < e->count; i++) {
3297 memcpy(buf+size,
3298 e->vector[i].iov_base,
3299 e->vector[i].iov_len);
3300 size += e->vector[i].iov_len;
3303 e->sendfile_header->data = buf;
3304 e->sendfile_header->length = size;
3305 e->sendfile_status = &status;
3306 e->count = 0;
3308 xconn->smb2.send_queue_len--;
3309 DLIST_REMOVE(xconn->smb2.send_queue, e);
3311 * This triggers the sendfile path via
3312 * the destructor.
3314 talloc_free(e->mem_ctx);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 return status;
3319 continue;
3322 ret = writev(xconn->transport.sock, e->vector, e->count);
3323 if (ret == 0) {
3324 /* propagate end of file */
3325 return NT_STATUS_INTERNAL_ERROR;
3327 err = socket_error_from_errno(ret, errno, &retry);
3328 if (retry) {
3329 /* retry later */
3330 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3331 return NT_STATUS_OK;
3333 if (err != 0) {
3334 return map_nt_error_from_unix_common(err);
3337 ok = iov_advance(&e->vector, &e->count, ret);
3338 if (!ok) {
3339 return NT_STATUS_INTERNAL_ERROR;
3342 if (e->count > 0) {
3343 /* we have more to write */
3344 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3345 return NT_STATUS_OK;
3348 xconn->smb2.send_queue_len--;
3349 DLIST_REMOVE(xconn->smb2.send_queue, e);
3350 talloc_free(e->mem_ctx);
3353 return NT_STATUS_OK;
3356 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3357 uint16_t fde_flags)
3359 struct smbd_server_connection *sconn = xconn->client->sconn;
3360 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3361 struct smbd_smb2_request *req = NULL;
3362 size_t min_recvfile_size = UINT32_MAX;
3363 int ret;
3364 int err;
3365 bool retry;
3366 NTSTATUS status;
3367 NTTIME now;
3369 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3371 * we're not supposed to do any io
3373 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3374 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3375 return NT_STATUS_OK;
3378 if (fde_flags & TEVENT_FD_WRITE) {
3379 status = smbd_smb2_flush_send_queue(xconn);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 return status;
3385 if (!(fde_flags & TEVENT_FD_READ)) {
3386 return NT_STATUS_OK;
3389 if (state->req == NULL) {
3390 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3391 return NT_STATUS_OK;
3394 again:
3395 if (!state->hdr.done) {
3396 state->hdr.done = true;
3398 state->vector.iov_base = (void *)state->hdr.nbt;
3399 state->vector.iov_len = NBT_HDR_SIZE;
3402 ret = readv(xconn->transport.sock, &state->vector, 1);
3403 if (ret == 0) {
3404 /* propagate end of file */
3405 return NT_STATUS_END_OF_FILE;
3407 err = socket_error_from_errno(ret, errno, &retry);
3408 if (retry) {
3409 /* retry later */
3410 TEVENT_FD_READABLE(xconn->transport.fde);
3411 return NT_STATUS_OK;
3413 if (err != 0) {
3414 return map_nt_error_from_unix_common(err);
3417 if (ret < state->vector.iov_len) {
3418 uint8_t *base;
3419 base = (uint8_t *)state->vector.iov_base;
3420 base += ret;
3421 state->vector.iov_base = (void *)base;
3422 state->vector.iov_len -= ret;
3423 /* we have more to read */
3424 TEVENT_FD_READABLE(xconn->transport.fde);
3425 return NT_STATUS_OK;
3428 if (state->pktlen > 0) {
3429 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3431 * Not a possible receivefile write.
3432 * Read the rest of the data.
3434 state->doing_receivefile = false;
3436 state->pktbuf = talloc_realloc(state->req,
3437 state->pktbuf,
3438 uint8_t,
3439 state->pktfull);
3440 if (state->pktbuf == NULL) {
3441 return NT_STATUS_NO_MEMORY;
3444 state->vector.iov_base = (void *)(state->pktbuf +
3445 state->pktlen);
3446 state->vector.iov_len = (state->pktfull -
3447 state->pktlen);
3449 state->pktlen = state->pktfull;
3450 goto again;
3454 * Either this is a receivefile write so we've
3455 * done a short read, or if not we have all the data.
3457 goto got_full;
3461 * Now we analyze the NBT header
3463 if (state->hdr.nbt[0] != 0x00) {
3464 state->min_recv_size = 0;
3466 state->pktfull = smb2_len(state->hdr.nbt);
3467 if (state->pktfull == 0) {
3468 goto got_full;
3471 if (state->min_recv_size != 0) {
3472 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3473 min_recvfile_size += state->min_recv_size;
3476 if (state->pktfull > min_recvfile_size) {
3478 * Might be a receivefile write. Read the SMB2 HEADER +
3479 * SMB2_WRITE header first. Set 'doing_receivefile'
3480 * as we're *attempting* receivefile write. If this
3481 * turns out not to be a SMB2_WRITE request or otherwise
3482 * not suitable then we'll just read the rest of the data
3483 * the next time this function is called.
3485 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3486 state->doing_receivefile = true;
3487 } else {
3488 state->pktlen = state->pktfull;
3491 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3492 if (state->pktbuf == NULL) {
3493 return NT_STATUS_NO_MEMORY;
3496 state->vector.iov_base = (void *)state->pktbuf;
3497 state->vector.iov_len = state->pktlen;
3499 goto again;
3501 got_full:
3503 if (state->hdr.nbt[0] != 0x00) {
3504 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3505 state->hdr.nbt[0]));
3507 req = state->req;
3508 ZERO_STRUCTP(state);
3509 state->req = req;
3510 state->min_recv_size = lp_min_receive_file_size();
3511 req = NULL;
3512 goto again;
3515 req = state->req;
3516 state->req = NULL;
3518 req->request_time = timeval_current();
3519 now = timeval_to_nttime(&req->request_time);
3521 status = smbd_smb2_inbuf_parse_compound(xconn,
3522 now,
3523 state->pktbuf,
3524 state->pktlen,
3525 req,
3526 &req->in.vector,
3527 &req->in.vector_count);
3528 if (!NT_STATUS_IS_OK(status)) {
3529 return status;
3532 if (state->doing_receivefile) {
3533 req->smb1req = talloc_zero(req, struct smb_request);
3534 if (req->smb1req == NULL) {
3535 return NT_STATUS_NO_MEMORY;
3537 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3540 ZERO_STRUCTP(state);
3542 req->current_idx = 1;
3544 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3545 req->current_idx, req->in.vector_count));
3547 status = smbd_smb2_request_validate(req);
3548 if (!NT_STATUS_IS_OK(status)) {
3549 return status;
3552 status = smbd_smb2_request_setup_out(req);
3553 if (!NT_STATUS_IS_OK(status)) {
3554 return status;
3557 status = smbd_smb2_request_dispatch(req);
3558 if (!NT_STATUS_IS_OK(status)) {
3559 return status;
3562 sconn->num_requests++;
3564 /* The timeout_processing function isn't run nearly
3565 often enough to implement 'max log size' without
3566 overrunning the size of the file by many megabytes.
3567 This is especially true if we are running at debug
3568 level 10. Checking every 50 SMB2s is a nice
3569 tradeoff of performance vs log file size overrun. */
3571 if ((sconn->num_requests % 50) == 0 &&
3572 need_to_check_log_size()) {
3573 change_to_root_user();
3574 check_log_size();
3577 status = smbd_smb2_request_next_incoming(xconn);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 return status;
3582 return NT_STATUS_OK;
3585 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3586 struct tevent_fd *fde,
3587 uint16_t flags,
3588 void *private_data)
3590 struct smbXsrv_connection *xconn =
3591 talloc_get_type_abort(private_data,
3592 struct smbXsrv_connection);
3593 NTSTATUS status;
3595 status = smbd_smb2_io_handler(xconn, flags);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 smbd_server_connection_terminate(xconn, nt_errstr(status));
3598 return;