s3:smbd: move sconn->smb1.negprot.* to xconn->smb1.negprot.*
[Samba.git] / source3 / smbd / smb2_server.c
blobbce60340bfa038d1191fe7be49cc0786888cf859
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "../lib/util/tevent_ntstatus.h"
28 #include "smbprofile.h"
29 #include "../lib/util/bitmap.h"
30 #include "../librpc/gen_ndr/krb5pac.h"
31 #include "auth.h"
33 static void smbd_smb2_connection_handler(struct tevent_context *ev,
34 struct tevent_fd *fde,
35 uint16_t flags,
36 void *private_data);
37 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn);
39 static const struct smbd_smb2_dispatch_table {
40 uint16_t opcode;
41 const char *name;
42 bool need_session;
43 bool need_tcon;
44 bool as_root;
45 uint16_t fileid_ofs;
46 bool allow_invalid_fileid;
47 } smbd_smb2_table[] = {
48 #define _OP(o) .opcode = o, .name = #o
50 _OP(SMB2_OP_NEGPROT),
51 .as_root = true,
52 },{
53 _OP(SMB2_OP_SESSSETUP),
54 .as_root = true,
55 },{
56 _OP(SMB2_OP_LOGOFF),
57 .need_session = true,
58 .as_root = true,
59 },{
60 _OP(SMB2_OP_TCON),
61 .need_session = true,
63 * This call needs to be run as root.
65 * smbd_smb2_request_process_tcon()
66 * calls make_connection_snum(), which will call
67 * change_to_user(), when needed.
69 .as_root = true,
70 },{
71 _OP(SMB2_OP_TDIS),
72 .need_session = true,
73 .need_tcon = true,
74 .as_root = true,
75 },{
76 _OP(SMB2_OP_CREATE),
77 .need_session = true,
78 .need_tcon = true,
79 },{
80 _OP(SMB2_OP_CLOSE),
81 .need_session = true,
82 .need_tcon = true,
83 .fileid_ofs = 0x08,
84 },{
85 _OP(SMB2_OP_FLUSH),
86 .need_session = true,
87 .need_tcon = true,
88 .fileid_ofs = 0x08,
89 },{
90 _OP(SMB2_OP_READ),
91 .need_session = true,
92 .need_tcon = true,
93 .fileid_ofs = 0x10,
94 },{
95 _OP(SMB2_OP_WRITE),
96 .need_session = true,
97 .need_tcon = true,
98 .fileid_ofs = 0x10,
99 },{
100 _OP(SMB2_OP_LOCK),
101 .need_session = true,
102 .need_tcon = true,
103 .fileid_ofs = 0x08,
105 _OP(SMB2_OP_IOCTL),
106 .need_session = true,
107 .need_tcon = true,
108 .fileid_ofs = 0x08,
109 .allow_invalid_fileid = true,
111 _OP(SMB2_OP_CANCEL),
112 .as_root = true,
114 _OP(SMB2_OP_KEEPALIVE),
115 .as_root = true,
117 _OP(SMB2_OP_FIND),
118 .need_session = true,
119 .need_tcon = true,
120 .fileid_ofs = 0x08,
122 _OP(SMB2_OP_NOTIFY),
123 .need_session = true,
124 .need_tcon = true,
125 .fileid_ofs = 0x08,
127 _OP(SMB2_OP_GETINFO),
128 .need_session = true,
129 .need_tcon = true,
130 .fileid_ofs = 0x18,
132 _OP(SMB2_OP_SETINFO),
133 .need_session = true,
134 .need_tcon = true,
135 .fileid_ofs = 0x10,
137 _OP(SMB2_OP_BREAK),
138 .need_session = true,
139 .need_tcon = true,
141 * we do not set
142 * .fileid_ofs here
143 * as LEASE breaks does not
144 * have a file id
149 const char *smb2_opcode_name(uint16_t opcode)
151 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
152 return "Bad SMB2 opcode";
154 return smbd_smb2_table[opcode].name;
157 static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
159 const struct smbd_smb2_dispatch_table *ret = NULL;
161 if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
162 return NULL;
165 ret = &smbd_smb2_table[opcode];
167 SMB_ASSERT(ret->opcode == opcode);
169 return ret;
172 static void print_req_vectors(const struct smbd_smb2_request *req)
174 int i;
176 for (i = 0; i < req->in.vector_count; i++) {
177 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
178 (unsigned int)i,
179 (unsigned int)req->in.vector[i].iov_len);
181 for (i = 0; i < req->out.vector_count; i++) {
182 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
183 (unsigned int)i,
184 (unsigned int)req->out.vector[i].iov_len);
188 bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
190 if (size < (4 + SMB2_HDR_BODY)) {
191 return false;
194 if (IVAL(inbuf, 4) != SMB2_MAGIC) {
195 return false;
198 return true;
201 static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
203 struct smbXsrv_connection *xconn = sconn->conn;
205 TALLOC_FREE(xconn->transport.fde);
207 sconn->smb2.send_queue = NULL;
209 sconn->smb2.seqnum_low = 0;
210 sconn->smb2.seqnum_range = 1;
211 sconn->smb2.credits_granted = 1;
212 sconn->smb2.max_credits = lp_smb2_max_credits();
213 sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
214 sconn->smb2.max_credits);
215 if (sconn->smb2.credits_bitmap == NULL) {
216 return NT_STATUS_NO_MEMORY;
219 sconn->smb2.fde = tevent_add_fd(sconn->ev_ctx,
220 sconn,
221 xconn->transport.sock,
222 TEVENT_FD_READ,
223 smbd_smb2_connection_handler,
224 sconn);
225 if (sconn->smb2.fde == NULL) {
226 return NT_STATUS_NO_MEMORY;
229 /* Ensure child is set to non-blocking mode */
230 set_blocking(xconn->transport.sock, false);
231 return NT_STATUS_OK;
234 #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
235 #define _smb2_setlen(_buf,len) do { \
236 uint8_t *buf = (uint8_t *)_buf; \
237 buf[0] = 0; \
238 buf[1] = ((len)&0xFF0000)>>16; \
239 buf[2] = ((len)&0xFF00)>>8; \
240 buf[3] = (len)&0xFF; \
241 } while (0)
243 static void smb2_setup_nbt_length(struct iovec *vector, int count)
245 size_t len = 0;
246 int i;
248 for (i=1; i < count; i++) {
249 len += vector[i].iov_len;
252 _smb2_setlen(vector[0].iov_base, len);
255 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
257 if (req->first_key.length > 0) {
258 data_blob_clear_free(&req->first_key);
260 if (req->last_key.length > 0) {
261 data_blob_clear_free(&req->last_key);
263 return 0;
266 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
268 TALLOC_CTX *mem_pool;
269 struct smbd_smb2_request *req;
271 #if 0
272 /* Enable this to find subtle valgrind errors. */
273 mem_pool = talloc_init("smbd_smb2_request_allocate");
274 #else
275 mem_pool = talloc_tos();
276 #endif
277 if (mem_pool == NULL) {
278 return NULL;
281 req = talloc_zero(mem_pool, struct smbd_smb2_request);
282 if (req == NULL) {
283 talloc_free(mem_pool);
284 return NULL;
286 talloc_reparent(mem_pool, mem_ctx, req);
287 #if 0
288 TALLOC_FREE(mem_pool);
289 #endif
291 req->last_session_id = UINT64_MAX;
292 req->last_tid = UINT32_MAX;
294 talloc_set_destructor(req, smbd_smb2_request_destructor);
296 return req;
299 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
300 NTTIME now,
301 uint8_t *buf,
302 size_t buflen,
303 struct smbd_smb2_request *req,
304 struct iovec **piov,
305 int *pnum_iov)
307 TALLOC_CTX *mem_ctx = req;
308 struct iovec *iov;
309 int num_iov = 1;
310 size_t taken = 0;
311 uint8_t *first_hdr = buf;
312 size_t verified_buflen = 0;
313 uint8_t *tf = NULL;
314 size_t tf_len = 0;
317 * Note: index '0' is reserved for the transport protocol
319 iov = req->in._vector;
321 while (taken < buflen) {
322 size_t len = buflen - taken;
323 uint8_t *hdr = first_hdr + taken;
324 struct iovec *cur;
325 size_t full_size;
326 size_t next_command_ofs;
327 uint16_t body_size;
328 uint8_t *body = NULL;
329 uint32_t dyn_size;
330 uint8_t *dyn = NULL;
331 struct iovec *iov_alloc = NULL;
333 if (iov != req->in._vector) {
334 iov_alloc = iov;
337 if (verified_buflen > taken) {
338 len = verified_buflen - taken;
339 } else {
340 tf = NULL;
341 tf_len = 0;
344 if (len < 4) {
345 DEBUG(10, ("%d bytes left, expected at least %d\n",
346 (int)len, 4));
347 goto inval;
349 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
350 struct smbXsrv_session *s = NULL;
351 uint64_t uid;
352 struct iovec tf_iov[2];
353 NTSTATUS status;
354 size_t enc_len;
356 if (conn->protocol < PROTOCOL_SMB2_24) {
357 DEBUG(10, ("Got SMB2_TRANSFORM header, "
358 "but dialect[0x%04X] is used\n",
359 conn->smb2.server.dialect));
360 goto inval;
363 if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
364 DEBUG(10, ("Got SMB2_TRANSFORM header, "
365 "but not negotiated "
366 "client[0x%08X] server[0x%08X]\n",
367 conn->smb2.client.capabilities,
368 conn->smb2.server.capabilities));
369 goto inval;
372 if (len < SMB2_TF_HDR_SIZE) {
373 DEBUG(1, ("%d bytes left, expected at least %d\n",
374 (int)len, SMB2_TF_HDR_SIZE));
375 goto inval;
377 tf = hdr;
378 tf_len = SMB2_TF_HDR_SIZE;
379 taken += tf_len;
381 hdr = first_hdr + taken;
382 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
383 uid = BVAL(tf, SMB2_TF_SESSION_ID);
385 if (len < SMB2_TF_HDR_SIZE + enc_len) {
386 DEBUG(1, ("%d bytes left, expected at least %d\n",
387 (int)len,
388 (int)(SMB2_TF_HDR_SIZE + enc_len)));
389 goto inval;
392 status = smb2srv_session_lookup(conn, uid, now, &s);
393 if (s == NULL) {
394 DEBUG(1, ("invalid session[%llu] in "
395 "SMB2_TRANSFORM header\n",
396 (unsigned long long)uid));
397 TALLOC_FREE(iov_alloc);
398 return NT_STATUS_USER_SESSION_DELETED;
401 tf_iov[0].iov_base = (void *)tf;
402 tf_iov[0].iov_len = tf_len;
403 tf_iov[1].iov_base = (void *)hdr;
404 tf_iov[1].iov_len = enc_len;
406 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
407 conn->protocol,
408 tf_iov, 2);
409 if (!NT_STATUS_IS_OK(status)) {
410 TALLOC_FREE(iov_alloc);
411 return status;
414 verified_buflen = taken + enc_len;
415 len = enc_len;
419 * We need the header plus the body length field
422 if (len < SMB2_HDR_BODY + 2) {
423 DEBUG(10, ("%d bytes left, expected at least %d\n",
424 (int)len, SMB2_HDR_BODY));
425 goto inval;
427 if (IVAL(hdr, 0) != SMB2_MAGIC) {
428 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
429 IVAL(hdr, 0)));
430 goto inval;
432 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
433 DEBUG(10, ("Got HDR len %d, expected %d\n",
434 SVAL(hdr, 4), SMB2_HDR_BODY));
435 goto inval;
438 full_size = len;
439 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
440 body_size = SVAL(hdr, SMB2_HDR_BODY);
442 if (next_command_ofs != 0) {
443 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
444 goto inval;
446 if (next_command_ofs > full_size) {
447 goto inval;
449 full_size = next_command_ofs;
451 if (body_size < 2) {
452 goto inval;
454 body_size &= 0xfffe;
456 if (body_size > (full_size - SMB2_HDR_BODY)) {
458 * let the caller handle the error
460 body_size = full_size - SMB2_HDR_BODY;
462 body = hdr + SMB2_HDR_BODY;
463 dyn = body + body_size;
464 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
466 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
467 struct iovec *iov_tmp = NULL;
469 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
470 struct iovec,
471 num_iov +
472 SMBD_SMB2_NUM_IOV_PER_REQ);
473 if (iov_tmp == NULL) {
474 TALLOC_FREE(iov_alloc);
475 return NT_STATUS_NO_MEMORY;
478 if (iov_alloc == NULL) {
479 memcpy(iov_tmp,
480 req->in._vector,
481 sizeof(req->in._vector));
484 iov = iov_tmp;
486 cur = &iov[num_iov];
487 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
489 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
490 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
491 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
492 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
493 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
494 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
495 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
496 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
498 taken += full_size;
501 *piov = iov;
502 *pnum_iov = num_iov;
503 return NT_STATUS_OK;
505 inval:
506 if (iov != req->in._vector) {
507 TALLOC_FREE(iov);
509 return NT_STATUS_INVALID_PARAMETER;
512 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
513 uint8_t *inbuf, size_t size,
514 struct smbd_smb2_request **_req)
516 struct smbd_smb2_request *req;
517 uint32_t protocol_version;
518 const uint8_t *inhdr = NULL;
519 uint16_t cmd;
520 uint32_t next_command_ofs;
521 NTSTATUS status;
522 NTTIME now;
524 if (size < (4 + SMB2_HDR_BODY + 2)) {
525 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
526 return NT_STATUS_INVALID_PARAMETER;
529 inhdr = inbuf + 4;
531 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
532 if (protocol_version != SMB2_MAGIC) {
533 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
534 protocol_version));
535 return NT_STATUS_INVALID_PARAMETER;
538 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
539 if (cmd != SMB2_OP_NEGPROT) {
540 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
541 cmd));
542 return NT_STATUS_INVALID_PARAMETER;
545 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
546 if (next_command_ofs != 0) {
547 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
548 next_command_ofs));
549 return NT_STATUS_INVALID_PARAMETER;
552 req = smbd_smb2_request_allocate(sconn);
553 if (req == NULL) {
554 return NT_STATUS_NO_MEMORY;
556 req->sconn = sconn;
558 talloc_steal(req, inbuf);
560 req->request_time = timeval_current();
561 now = timeval_to_nttime(&req->request_time);
563 status = smbd_smb2_inbuf_parse_compound(sconn->conn,
564 now,
565 inbuf + NBT_HDR_SIZE,
566 size - NBT_HDR_SIZE,
567 req, &req->in.vector,
568 &req->in.vector_count);
569 if (!NT_STATUS_IS_OK(status)) {
570 TALLOC_FREE(req);
571 return status;
574 req->current_idx = 1;
576 *_req = req;
577 return NT_STATUS_OK;
580 static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
581 uint64_t message_id, uint64_t seq_id)
583 struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
584 unsigned int offset;
586 if (seq_id < sconn->smb2.seqnum_low) {
587 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
588 "%llu (sequence id %llu) "
589 "(granted = %u, low = %llu, range = %u)\n",
590 (unsigned long long)message_id,
591 (unsigned long long)seq_id,
592 (unsigned int)sconn->smb2.credits_granted,
593 (unsigned long long)sconn->smb2.seqnum_low,
594 (unsigned int)sconn->smb2.seqnum_range));
595 return false;
598 if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
599 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
600 "%llu (sequence id %llu) "
601 "(granted = %u, low = %llu, range = %u)\n",
602 (unsigned long long)message_id,
603 (unsigned long long)seq_id,
604 (unsigned int)sconn->smb2.credits_granted,
605 (unsigned long long)sconn->smb2.seqnum_low,
606 (unsigned int)sconn->smb2.seqnum_range));
607 return false;
610 offset = seq_id % sconn->smb2.max_credits;
612 if (bitmap_query(credits_bm, offset)) {
613 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
614 "%llu (sequence id %llu) "
615 "(granted = %u, low = %llu, range = %u) "
616 "(bm offset %u)\n",
617 (unsigned long long)message_id,
618 (unsigned long long)seq_id,
619 (unsigned int)sconn->smb2.credits_granted,
620 (unsigned long long)sconn->smb2.seqnum_low,
621 (unsigned int)sconn->smb2.seqnum_range,
622 offset));
623 return false;
626 /* Mark the message_ids as seen in the bitmap. */
627 bitmap_set(credits_bm, offset);
629 if (seq_id != sconn->smb2.seqnum_low) {
630 return true;
634 * Move the window forward by all the message_id's
635 * already seen.
637 while (bitmap_query(credits_bm, offset)) {
638 DEBUG(10,("smb2_validate_sequence_number: clearing "
639 "id %llu (position %u) from bitmap\n",
640 (unsigned long long)(sconn->smb2.seqnum_low),
641 offset));
642 bitmap_clear(credits_bm, offset);
644 sconn->smb2.seqnum_low += 1;
645 sconn->smb2.seqnum_range -= 1;
646 offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
649 return true;
652 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
653 const uint8_t *inhdr)
655 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
656 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
657 uint16_t credit_charge = 1;
658 uint64_t i;
660 if (opcode == SMB2_OP_CANCEL) {
661 /* SMB2_CANCEL requests by definition resend messageids. */
662 return true;
665 if (sconn->smb2.supports_multicredit) {
666 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
667 credit_charge = MAX(credit_charge, 1);
670 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
671 "credits_granted %llu, "
672 "seqnum low/range: %llu/%llu\n",
673 (unsigned long long) message_id,
674 (unsigned long long) credit_charge,
675 (unsigned long long) sconn->smb2.credits_granted,
676 (unsigned long long) sconn->smb2.seqnum_low,
677 (unsigned long long) sconn->smb2.seqnum_range));
679 if (sconn->smb2.credits_granted < credit_charge) {
680 DEBUG(0, ("smb2_validate_message_id: client used more "
681 "credits than granted, mid %llu, charge %llu, "
682 "credits_granted %llu, "
683 "seqnum low/range: %llu/%llu\n",
684 (unsigned long long) message_id,
685 (unsigned long long) credit_charge,
686 (unsigned long long) sconn->smb2.credits_granted,
687 (unsigned long long) sconn->smb2.seqnum_low,
688 (unsigned long long) sconn->smb2.seqnum_range));
689 return false;
693 * now check the message ids
695 * for multi-credit requests we need to check all current mid plus
696 * the implicit mids caused by the credit charge
697 * e.g. current mid = 15, charge 5 => mark 15-19 as used
700 for (i = 0; i <= (credit_charge-1); i++) {
701 uint64_t id = message_id + i;
702 bool ok;
704 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
705 (unsigned long long)message_id,
706 credit_charge,
707 (unsigned long long)id));
709 ok = smb2_validate_sequence_number(sconn, message_id, id);
710 if (!ok) {
711 return false;
715 /* substract used credits */
716 sconn->smb2.credits_granted -= credit_charge;
718 return true;
721 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
723 int count;
724 int idx;
726 count = req->in.vector_count;
728 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
729 /* It's not a SMB2 request */
730 return NT_STATUS_INVALID_PARAMETER;
733 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
734 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
735 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
736 const uint8_t *inhdr = NULL;
738 if (hdr->iov_len != SMB2_HDR_BODY) {
739 return NT_STATUS_INVALID_PARAMETER;
742 if (body->iov_len < 2) {
743 return NT_STATUS_INVALID_PARAMETER;
746 inhdr = (const uint8_t *)hdr->iov_base;
748 /* Check the SMB2 header */
749 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
750 return NT_STATUS_INVALID_PARAMETER;
753 if (!smb2_validate_message_id(req->sconn, inhdr)) {
754 return NT_STATUS_INVALID_PARAMETER;
758 return NT_STATUS_OK;
761 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
762 const struct iovec *in_vector,
763 struct iovec *out_vector)
765 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
766 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
767 uint16_t credit_charge = 1;
768 uint16_t credits_requested;
769 uint32_t out_flags;
770 uint16_t cmd;
771 NTSTATUS out_status;
772 uint16_t credits_granted = 0;
773 uint64_t credits_possible;
774 uint16_t current_max_credits;
777 * first we grant only 1/16th of the max range.
779 * Windows also starts with the 1/16th and then grants
780 * more later. I was only able to trigger higher
781 * values, when using a very high credit charge.
783 * TODO: scale up depending on load, free memory
784 * or other stuff.
785 * Maybe also on the relationship between number
786 * of requests and the used sequence number.
787 * Which means we would grant more credits
788 * for client which use multi credit requests.
790 current_max_credits = sconn->smb2.max_credits / 16;
791 current_max_credits = MAX(current_max_credits, 1);
793 if (sconn->smb2.supports_multicredit) {
794 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
795 credit_charge = MAX(credit_charge, 1);
798 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
799 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
800 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
801 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
803 SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
805 if (sconn->smb2.max_credits < credit_charge) {
806 smbd_server_connection_terminate(sconn,
807 "client error: credit charge > max credits\n");
808 return;
811 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
813 * In case we already send an async interim
814 * response, we should not grant
815 * credits on the final response.
817 credits_granted = 0;
818 } else if (credits_requested > 0) {
819 uint16_t additional_max = 0;
820 uint16_t additional_credits = credits_requested - 1;
822 switch (cmd) {
823 case SMB2_OP_NEGPROT:
824 break;
825 case SMB2_OP_SESSSETUP:
827 * Windows 2012 RC1 starts to grant
828 * additional credits
829 * with a successful session setup
831 if (NT_STATUS_IS_OK(out_status)) {
832 additional_max = 32;
834 break;
835 default:
837 * We match windows and only grant additional credits
838 * in chunks of 32.
840 additional_max = 32;
841 break;
844 additional_credits = MIN(additional_credits, additional_max);
846 credits_granted = credit_charge + additional_credits;
847 } else if (sconn->smb2.credits_granted == 0) {
849 * Make sure the client has always at least one credit
851 credits_granted = 1;
855 * sequence numbers should not wrap
857 * 1. calculate the possible credits until
858 * the sequence numbers start to wrap on 64-bit.
860 * 2. UINT64_MAX is used for Break Notifications.
862 * 2. truncate the possible credits to the maximum
863 * credits we want to grant to the client in total.
865 * 3. remove the range we'll already granted to the client
866 * this makes sure the client consumes the lowest sequence
867 * number, before we can grant additional credits.
869 credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
870 if (credits_possible > 0) {
871 /* remove UINT64_MAX */
872 credits_possible -= 1;
874 credits_possible = MIN(credits_possible, current_max_credits);
875 credits_possible -= sconn->smb2.seqnum_range;
877 credits_granted = MIN(credits_granted, credits_possible);
879 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
880 sconn->smb2.credits_granted += credits_granted;
881 sconn->smb2.seqnum_range += credits_granted;
883 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
884 "granted %u, current possible/max %u/%u, "
885 "total granted/max/low/range %u/%u/%llu/%u\n",
886 (unsigned int)credits_requested,
887 (unsigned int)credit_charge,
888 (unsigned int)credits_granted,
889 (unsigned int)credits_possible,
890 (unsigned int)current_max_credits,
891 (unsigned int)sconn->smb2.credits_granted,
892 (unsigned int)sconn->smb2.max_credits,
893 (unsigned long long)sconn->smb2.seqnum_low,
894 (unsigned int)sconn->smb2.seqnum_range));
897 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
898 struct smbd_smb2_request *outreq)
900 int count, idx;
901 uint16_t total_credits = 0;
903 count = outreq->out.vector_count;
905 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
906 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
907 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
908 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
910 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
912 /* To match Windows, count up what we
913 just granted. */
914 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
915 /* Set to zero in all but the last reply. */
916 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
917 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
918 } else {
919 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
924 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
926 if (req->current_idx <= 1) {
927 if (size <= sizeof(req->out._body)) {
928 return data_blob_const(req->out._body, size);
932 return data_blob_talloc(req, NULL, size);
935 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
937 TALLOC_CTX *mem_ctx;
938 struct iovec *vector;
939 int count;
940 int idx;
942 count = req->in.vector_count;
943 if (count <= ARRAY_SIZE(req->out._vector)) {
944 mem_ctx = req;
945 vector = req->out._vector;
946 } else {
947 vector = talloc_zero_array(req, struct iovec, count);
948 if (vector == NULL) {
949 return NT_STATUS_NO_MEMORY;
951 mem_ctx = vector;
954 vector[0].iov_base = req->out.nbt_hdr;
955 vector[0].iov_len = 4;
956 SIVAL(req->out.nbt_hdr, 0, 0);
958 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
959 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
960 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
961 uint8_t *outhdr = NULL;
962 uint8_t *outbody = NULL;
963 uint32_t next_command_ofs = 0;
964 struct iovec *current = &vector[idx];
966 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
967 /* we have a next command -
968 * setup for the error case. */
969 next_command_ofs = SMB2_HDR_BODY + 9;
972 if (idx == 1) {
973 outhdr = req->out._hdr;
974 } else {
975 outhdr = talloc_zero_array(mem_ctx, uint8_t,
976 OUTVEC_ALLOC_SIZE);
977 if (outhdr == NULL) {
978 return NT_STATUS_NO_MEMORY;
982 outbody = outhdr + SMB2_HDR_BODY;
985 * SMBD_SMB2_TF_IOV_OFS might be used later
987 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
988 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
990 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
991 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
993 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
994 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
996 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
997 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
999 /* setup the SMB2 header */
1000 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1001 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1002 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1003 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1004 SIVAL(outhdr, SMB2_HDR_STATUS,
1005 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1006 SSVAL(outhdr, SMB2_HDR_OPCODE,
1007 SVAL(inhdr, SMB2_HDR_OPCODE));
1008 SIVAL(outhdr, SMB2_HDR_FLAGS,
1009 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1010 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1011 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1012 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1013 SIVAL(outhdr, SMB2_HDR_PID,
1014 IVAL(inhdr, SMB2_HDR_PID));
1015 SIVAL(outhdr, SMB2_HDR_TID,
1016 IVAL(inhdr, SMB2_HDR_TID));
1017 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1018 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1019 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1020 inhdr + SMB2_HDR_SIGNATURE, 16);
1022 /* setup error body header */
1023 SSVAL(outbody, 0x00, 0x08 + 1);
1024 SSVAL(outbody, 0x02, 0);
1025 SIVAL(outbody, 0x04, 0);
1028 req->out.vector = vector;
1029 req->out.vector_count = count;
1031 /* setup the length of the NBT packet */
1032 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1034 DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
1036 return NT_STATUS_OK;
1039 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1040 const char *reason,
1041 const char *location)
1043 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1044 reason, location));
1045 exit_server_cleanly(reason);
1048 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1049 struct iovec *outvec,
1050 const struct iovec *srcvec)
1052 const uint8_t *srctf;
1053 size_t srctf_len;
1054 const uint8_t *srchdr;
1055 size_t srchdr_len;
1056 const uint8_t *srcbody;
1057 size_t srcbody_len;
1058 const uint8_t *expected_srcbody;
1059 const uint8_t *srcdyn;
1060 size_t srcdyn_len;
1061 const uint8_t *expected_srcdyn;
1062 uint8_t *dsttf;
1063 uint8_t *dsthdr;
1064 uint8_t *dstbody;
1065 uint8_t *dstdyn;
1067 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1068 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1069 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1070 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1071 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1072 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1073 expected_srcbody = srchdr + SMB2_HDR_BODY;
1074 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1075 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1076 expected_srcdyn = srcbody + 8;
1078 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1079 return false;
1082 if (srchdr_len != SMB2_HDR_BODY) {
1083 return false;
1086 if (srctf_len == SMB2_TF_HDR_SIZE) {
1087 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1088 if (dsttf == NULL) {
1089 return false;
1091 } else {
1092 dsttf = NULL;
1094 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1095 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1097 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1098 * be allocated with size OUTVEC_ALLOC_SIZE. */
1100 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1101 if (dsthdr == NULL) {
1102 return false;
1104 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1105 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1108 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1109 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1110 * then duplicate this. Else use talloc_memdup().
1113 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1114 dstbody = dsthdr + SMB2_HDR_BODY;
1115 } else {
1116 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1117 if (dstbody == NULL) {
1118 return false;
1121 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1122 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1125 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1126 * pointing to
1127 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1128 * then duplicate this. Else use talloc_memdup().
1131 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1132 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1133 } else if (srcdyn == NULL) {
1134 dstdyn = NULL;
1135 } else {
1136 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1137 if (dstdyn == NULL) {
1138 return false;
1141 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1142 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1144 return true;
1147 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1149 struct smbd_smb2_request *newreq = NULL;
1150 struct iovec *outvec = NULL;
1151 int count = req->out.vector_count;
1152 int i;
1154 newreq = smbd_smb2_request_allocate(req->sconn);
1155 if (!newreq) {
1156 return NULL;
1159 newreq->sconn = req->sconn;
1160 newreq->session = req->session;
1161 newreq->do_encryption = req->do_encryption;
1162 newreq->do_signing = req->do_signing;
1163 newreq->current_idx = req->current_idx;
1165 outvec = talloc_zero_array(newreq, struct iovec, count);
1166 if (!outvec) {
1167 TALLOC_FREE(newreq);
1168 return NULL;
1170 newreq->out.vector = outvec;
1171 newreq->out.vector_count = count;
1173 /* Setup the outvec's identically to req. */
1174 outvec[0].iov_base = newreq->out.nbt_hdr;
1175 outvec[0].iov_len = 4;
1176 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1178 /* Setup the vectors identically to the ones in req. */
1179 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1180 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1181 break;
1185 if (i < count) {
1186 /* Alloc failed. */
1187 TALLOC_FREE(newreq);
1188 return NULL;
1191 smb2_setup_nbt_length(newreq->out.vector,
1192 newreq->out.vector_count);
1194 return newreq;
1197 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1199 struct smbd_server_connection *sconn = req->sconn;
1200 struct smbXsrv_connection *conn = req->sconn->conn;
1201 int first_idx = 1;
1202 struct iovec *firsttf = NULL;
1203 struct iovec *outhdr_v = NULL;
1204 uint8_t *outhdr = NULL;
1205 struct smbd_smb2_request *nreq = NULL;
1206 NTSTATUS status;
1208 /* Create a new smb2 request we'll use
1209 for the interim return. */
1210 nreq = dup_smb2_req(req);
1211 if (!nreq) {
1212 return NT_STATUS_NO_MEMORY;
1215 /* Lose the last X out vectors. They're the
1216 ones we'll be using for the async reply. */
1217 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1219 smb2_setup_nbt_length(nreq->out.vector,
1220 nreq->out.vector_count);
1222 /* Step back to the previous reply. */
1223 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1224 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1225 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1226 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1227 /* And end the chain. */
1228 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1230 /* Calculate outgoing credits */
1231 smb2_calculate_credits(req, nreq);
1233 if (DEBUGLEVEL >= 10) {
1234 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1235 (unsigned int)nreq->current_idx );
1236 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1237 (unsigned int)nreq->out.vector_count );
1238 print_req_vectors(nreq);
1242 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1243 * we need to sign/encrypt here with the last/first key we remembered
1245 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1246 status = smb2_signing_encrypt_pdu(req->first_key,
1247 conn->protocol,
1248 firsttf,
1249 nreq->out.vector_count - first_idx);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 return status;
1253 } else if (req->last_key.length > 0) {
1254 status = smb2_signing_sign_pdu(req->last_key,
1255 conn->protocol,
1256 outhdr_v,
1257 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1258 if (!NT_STATUS_IS_OK(status)) {
1259 return status;
1263 nreq->queue_entry.mem_ctx = nreq;
1264 nreq->queue_entry.vector = nreq->out.vector;
1265 nreq->queue_entry.count = nreq->out.vector_count;
1266 DLIST_ADD_END(nreq->sconn->smb2.send_queue, &nreq->queue_entry, NULL);
1267 nreq->sconn->smb2.send_queue_len++;
1269 status = smbd_smb2_flush_send_queue(sconn);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 return status;
1274 return NT_STATUS_OK;
1277 struct smbd_smb2_request_pending_state {
1278 struct smbd_server_connection *sconn;
1279 struct smbd_smb2_send_queue queue_entry;
1280 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1281 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1284 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1285 struct tevent_timer *te,
1286 struct timeval current_time,
1287 void *private_data);
1289 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1290 struct tevent_req *subreq,
1291 uint32_t defer_time)
1293 NTSTATUS status;
1294 struct timeval defer_endtime;
1295 uint8_t *outhdr = NULL;
1296 uint32_t flags;
1298 if (!tevent_req_is_in_progress(subreq)) {
1300 * This is a performance optimization,
1301 * it avoids one tevent_loop iteration,
1302 * which means we avoid one
1303 * talloc_stackframe_pool/talloc_free pair.
1305 tevent_req_notify_callback(subreq);
1306 return NT_STATUS_OK;
1309 req->subreq = subreq;
1310 subreq = NULL;
1312 if (req->async_te) {
1313 /* We're already async. */
1314 return NT_STATUS_OK;
1317 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1318 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1319 if (flags & SMB2_HDR_FLAG_ASYNC) {
1320 /* We're already async. */
1321 return NT_STATUS_OK;
1324 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1326 * We're trying to go async in a compound
1327 * request chain.
1328 * This is only allowed for opens that
1329 * cause an oplock break, otherwise it
1330 * is not allowed. See [MS-SMB2].pdf
1331 * note <194> on Section 3.3.5.2.7.
1333 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1335 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1337 * Cancel the outstanding request.
1339 bool ok = tevent_req_cancel(req->subreq);
1340 if (ok) {
1341 return NT_STATUS_OK;
1343 TALLOC_FREE(req->subreq);
1344 return smbd_smb2_request_error(req,
1345 NT_STATUS_INTERNAL_ERROR);
1349 if (DEBUGLEVEL >= 10) {
1350 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1351 (unsigned int)req->current_idx );
1352 print_req_vectors(req);
1355 if (req->current_idx > 1) {
1357 * We're going async in a compound
1358 * chain after the first request has
1359 * already been processed. Send an
1360 * interim response containing the
1361 * set of replies already generated.
1363 int idx = req->current_idx;
1365 status = smb2_send_async_interim_response(req);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 return status;
1369 if (req->first_key.length > 0) {
1370 data_blob_clear_free(&req->first_key);
1373 req->current_idx = 1;
1376 * Re-arrange the in.vectors to remove what
1377 * we just sent.
1379 memmove(&req->in.vector[1],
1380 &req->in.vector[idx],
1381 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1382 req->in.vector_count = 1 + (req->in.vector_count - idx);
1384 /* Re-arrange the out.vectors to match. */
1385 memmove(&req->out.vector[1],
1386 &req->out.vector[idx],
1387 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1388 req->out.vector_count = 1 + (req->out.vector_count - idx);
1390 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1392 * We only have one remaining request as
1393 * we've processed everything else.
1394 * This is no longer a compound request.
1396 req->compound_related = false;
1397 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1398 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1399 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1402 if (req->last_key.length > 0) {
1403 data_blob_clear_free(&req->last_key);
1406 defer_endtime = timeval_current_ofs_usec(defer_time);
1407 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1408 req, defer_endtime,
1409 smbd_smb2_request_pending_timer,
1410 req);
1411 if (req->async_te == NULL) {
1412 return NT_STATUS_NO_MEMORY;
1415 return NT_STATUS_OK;
1418 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1419 struct tevent_timer *te,
1420 struct timeval current_time,
1421 void *private_data)
1423 struct smbd_smb2_request *req =
1424 talloc_get_type_abort(private_data,
1425 struct smbd_smb2_request);
1426 struct smbd_server_connection *sconn = req->sconn;
1427 struct smbd_smb2_request_pending_state *state = NULL;
1428 uint8_t *outhdr = NULL;
1429 const uint8_t *inhdr = NULL;
1430 uint8_t *tf = NULL;
1431 size_t tf_len = 0;
1432 uint8_t *hdr = NULL;
1433 uint8_t *body = NULL;
1434 uint8_t *dyn = NULL;
1435 uint32_t flags = 0;
1436 uint64_t session_id = 0;
1437 uint64_t message_id = 0;
1438 uint64_t nonce_high = 0;
1439 uint64_t nonce_low = 0;
1440 uint64_t async_id = 0;
1441 NTSTATUS status;
1443 TALLOC_FREE(req->async_te);
1445 /* Ensure our final reply matches the interim one. */
1446 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1447 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1448 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1449 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1450 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1452 async_id = message_id; /* keep it simple for now... */
1454 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1455 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1457 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1458 "going async\n",
1459 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1460 (unsigned long long)async_id ));
1463 * What we send is identical to a smbd_smb2_request_error
1464 * packet with an error status of STATUS_PENDING. Make use
1465 * of this fact sometime when refactoring. JRA.
1468 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1469 if (state == NULL) {
1470 smbd_server_connection_terminate(req->sconn,
1471 nt_errstr(NT_STATUS_NO_MEMORY));
1472 return;
1474 state->sconn = req->sconn;
1476 tf = state->buf + NBT_HDR_SIZE;
1477 tf_len = SMB2_TF_HDR_SIZE;
1479 hdr = tf + SMB2_TF_HDR_SIZE;
1480 body = hdr + SMB2_HDR_BODY;
1481 dyn = body + 8;
1483 if (req->do_encryption) {
1484 struct smbXsrv_session *x = req->session;
1486 nonce_high = x->nonce_high;
1487 nonce_low = x->nonce_low;
1489 x->nonce_low += 1;
1490 if (x->nonce_low == 0) {
1491 x->nonce_low += 1;
1492 x->nonce_high += 1;
1496 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1497 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1498 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1499 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1501 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1502 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1503 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1504 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1505 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1507 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1508 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1509 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1510 SBVAL(hdr, SMB2_HDR_PID, async_id);
1511 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1512 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1513 memcpy(hdr+SMB2_HDR_SIGNATURE,
1514 outhdr+SMB2_HDR_SIGNATURE, 16);
1516 SSVAL(body, 0x00, 0x08 + 1);
1518 SCVAL(body, 0x02, 0);
1519 SCVAL(body, 0x03, 0);
1520 SIVAL(body, 0x04, 0);
1521 /* Match W2K8R2... */
1522 SCVAL(dyn, 0x00, 0x21);
1524 state->vector[0].iov_base = (void *)state->buf;
1525 state->vector[0].iov_len = NBT_HDR_SIZE;
1527 if (req->do_encryption) {
1528 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1529 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1530 } else {
1531 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1532 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1535 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1536 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1538 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1539 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1541 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1542 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1544 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1546 /* Ensure we correctly go through crediting. Grant
1547 the credits now, and zero credits on the final
1548 response. */
1549 smb2_set_operation_credit(req->sconn,
1550 SMBD_SMB2_IN_HDR_IOV(req),
1551 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1553 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1555 if (DEBUGLVL(10)) {
1556 int i;
1558 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1559 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1560 (unsigned int)i,
1561 (unsigned int)ARRAY_SIZE(state->vector),
1562 (unsigned int)state->vector[i].iov_len);
1566 if (req->do_encryption) {
1567 struct smbXsrv_session *x = req->session;
1568 struct smbXsrv_connection *conn = x->connection;
1569 DATA_BLOB encryption_key = x->global->encryption_key;
1571 status = smb2_signing_encrypt_pdu(encryption_key,
1572 conn->protocol,
1573 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1574 SMBD_SMB2_NUM_IOV_PER_REQ);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 smbd_server_connection_terminate(req->sconn,
1577 nt_errstr(status));
1578 return;
1580 } else if (req->do_signing) {
1581 struct smbXsrv_session *x = req->session;
1582 struct smbXsrv_connection *conn = x->connection;
1583 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1585 status = smb2_signing_sign_pdu(signing_key,
1586 conn->protocol,
1587 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1588 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 smbd_server_connection_terminate(req->sconn,
1591 nt_errstr(status));
1592 return;
1596 state->queue_entry.mem_ctx = state;
1597 state->queue_entry.vector = state->vector;
1598 state->queue_entry.count = ARRAY_SIZE(state->vector);
1599 DLIST_ADD_END(sconn->smb2.send_queue, &state->queue_entry, NULL);
1600 sconn->smb2.send_queue_len++;
1602 status = smbd_smb2_flush_send_queue(sconn);
1603 if (!NT_STATUS_IS_OK(status)) {
1604 smbd_server_connection_terminate(sconn,
1605 nt_errstr(status));
1606 return;
1610 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1612 struct smbd_server_connection *sconn = req->sconn;
1613 struct smbd_smb2_request *cur;
1614 const uint8_t *inhdr;
1615 uint32_t flags;
1616 uint64_t search_message_id;
1617 uint64_t search_async_id;
1618 uint64_t found_id;
1620 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1622 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1623 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1624 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1627 * we don't need the request anymore
1628 * cancel requests never have a response
1630 DLIST_REMOVE(req->sconn->smb2.requests, req);
1631 TALLOC_FREE(req);
1633 for (cur = sconn->smb2.requests; cur; cur = cur->next) {
1634 const uint8_t *outhdr;
1635 uint64_t message_id;
1636 uint64_t async_id;
1638 if (cur->compound_related) {
1640 * Never cancel anything in a compound request.
1641 * Way too hard to deal with the result.
1643 continue;
1646 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1648 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1649 async_id = BVAL(outhdr, SMB2_HDR_PID);
1651 if (flags & SMB2_HDR_FLAG_ASYNC) {
1652 if (search_async_id == async_id) {
1653 found_id = async_id;
1654 break;
1656 } else {
1657 if (search_message_id == message_id) {
1658 found_id = message_id;
1659 break;
1664 if (cur && cur->subreq) {
1665 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1666 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1667 "cancel opcode[%s] mid %llu\n",
1668 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1669 (unsigned long long)found_id ));
1670 tevent_req_cancel(cur->subreq);
1673 return NT_STATUS_OK;
1676 /*************************************************************
1677 Ensure an incoming tid is a valid one for us to access.
1678 Change to the associated uid credentials and chdir to the
1679 valid tid directory.
1680 *************************************************************/
1682 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1684 const uint8_t *inhdr;
1685 uint32_t in_flags;
1686 uint32_t in_tid;
1687 struct smbXsrv_tcon *tcon;
1688 NTSTATUS status;
1689 NTTIME now = timeval_to_nttime(&req->request_time);
1691 req->tcon = NULL;
1693 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1695 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1696 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1698 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1699 in_tid = req->last_tid;
1702 req->last_tid = 0;
1704 status = smb2srv_tcon_lookup(req->session,
1705 in_tid, now, &tcon);
1706 if (!NT_STATUS_IS_OK(status)) {
1707 return status;
1710 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1711 return NT_STATUS_ACCESS_DENIED;
1714 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1715 if (!set_current_service(tcon->compat, 0, true)) {
1716 return NT_STATUS_ACCESS_DENIED;
1719 req->tcon = tcon;
1720 req->last_tid = in_tid;
1722 return NT_STATUS_OK;
1725 /*************************************************************
1726 Ensure an incoming session_id is a valid one for us to access.
1727 *************************************************************/
1729 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1731 const uint8_t *inhdr;
1732 uint32_t in_flags;
1733 uint16_t in_opcode;
1734 uint64_t in_session_id;
1735 struct smbXsrv_session *session = NULL;
1736 struct auth_session_info *session_info;
1737 NTSTATUS status;
1738 NTTIME now = timeval_to_nttime(&req->request_time);
1740 req->session = NULL;
1741 req->tcon = NULL;
1743 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1745 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1746 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1747 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1749 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1750 in_session_id = req->last_session_id;
1753 req->last_session_id = 0;
1755 /* lookup an existing session */
1756 status = smb2srv_session_lookup(req->sconn->conn,
1757 in_session_id, now,
1758 &session);
1759 if (session) {
1760 req->session = session;
1761 req->last_session_id = in_session_id;
1763 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1764 switch (in_opcode) {
1765 case SMB2_OP_SESSSETUP:
1766 status = NT_STATUS_OK;
1767 break;
1768 default:
1769 break;
1772 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1773 switch (in_opcode) {
1774 case SMB2_OP_TCON:
1775 case SMB2_OP_CREATE:
1776 case SMB2_OP_GETINFO:
1777 case SMB2_OP_SETINFO:
1778 return NT_STATUS_INVALID_HANDLE;
1779 default:
1781 * Notice the check for
1782 * (session_info == NULL)
1783 * below.
1785 status = NT_STATUS_OK;
1786 break;
1789 if (!NT_STATUS_IS_OK(status)) {
1790 return status;
1793 session_info = session->global->auth_session_info;
1794 if (session_info == NULL) {
1795 return NT_STATUS_INVALID_HANDLE;
1798 if (in_session_id != req->sconn->conn->last_session_id) {
1799 req->sconn->conn->last_session_id = in_session_id;
1800 set_current_user_info(session_info->unix_info->sanitized_username,
1801 session_info->unix_info->unix_name,
1802 session_info->info->domain_name);
1805 return NT_STATUS_OK;
1808 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1809 uint32_t data_length)
1811 uint16_t needed_charge;
1812 uint16_t credit_charge = 1;
1813 const uint8_t *inhdr;
1815 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1817 if (req->sconn->smb2.supports_multicredit) {
1818 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1819 credit_charge = MAX(credit_charge, 1);
1822 needed_charge = (data_length - 1)/ 65536 + 1;
1824 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1825 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1826 credit_charge, needed_charge));
1828 if (needed_charge > credit_charge) {
1829 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1830 credit_charge, needed_charge));
1831 return NT_STATUS_INVALID_PARAMETER;
1834 return NT_STATUS_OK;
1837 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1838 size_t expected_body_size)
1840 struct iovec *inhdr_v;
1841 const uint8_t *inhdr;
1842 uint16_t opcode;
1843 const uint8_t *inbody;
1844 size_t body_size;
1845 size_t min_dyn_size = expected_body_size & 0x00000001;
1846 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1849 * The following should be checked already.
1851 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1852 return NT_STATUS_INTERNAL_ERROR;
1854 if (req->current_idx > max_idx) {
1855 return NT_STATUS_INTERNAL_ERROR;
1858 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1859 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1860 return NT_STATUS_INTERNAL_ERROR;
1862 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1863 return NT_STATUS_INTERNAL_ERROR;
1866 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1867 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1869 switch (opcode) {
1870 case SMB2_OP_IOCTL:
1871 case SMB2_OP_GETINFO:
1872 min_dyn_size = 0;
1873 break;
1874 case SMB2_OP_WRITE:
1875 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1876 if (req->smb1req->unread_bytes < min_dyn_size) {
1877 return NT_STATUS_INVALID_PARAMETER;
1880 min_dyn_size = 0;
1882 break;
1886 * Now check the expected body size,
1887 * where the last byte might be in the
1888 * dynamic section..
1890 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1891 return NT_STATUS_INVALID_PARAMETER;
1893 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1894 return NT_STATUS_INVALID_PARAMETER;
1897 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1899 body_size = SVAL(inbody, 0x00);
1900 if (body_size != expected_body_size) {
1901 return NT_STATUS_INVALID_PARAMETER;
1904 return NT_STATUS_OK;
1907 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1909 struct smbXsrv_connection *conn = req->sconn->conn;
1910 const struct smbd_smb2_dispatch_table *call = NULL;
1911 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1912 const uint8_t *inhdr;
1913 uint16_t opcode;
1914 uint32_t flags;
1915 uint64_t mid;
1916 NTSTATUS status;
1917 NTSTATUS session_status;
1918 uint32_t allowed_flags;
1919 NTSTATUS return_value;
1920 struct smbXsrv_session *x = NULL;
1921 bool signing_required = false;
1922 bool encryption_required = false;
1924 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1926 /* TODO: verify more things */
1928 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1929 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1930 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1931 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1932 smb2_opcode_name(opcode),
1933 (unsigned long long)mid));
1935 if (conn->protocol >= PROTOCOL_SMB2_02) {
1937 * once the protocol is negotiated
1938 * SMB2_OP_NEGPROT is not allowed anymore
1940 if (opcode == SMB2_OP_NEGPROT) {
1941 /* drop the connection */
1942 return NT_STATUS_INVALID_PARAMETER;
1944 } else {
1946 * if the protocol is not negotiated yet
1947 * only SMB2_OP_NEGPROT is allowed.
1949 if (opcode != SMB2_OP_NEGPROT) {
1950 /* drop the connection */
1951 return NT_STATUS_INVALID_PARAMETER;
1956 * Check if the client provided a valid session id,
1957 * if so smbd_smb2_request_check_session() calls
1958 * set_current_user_info().
1960 * As some command don't require a valid session id
1961 * we defer the check of the session_status
1963 session_status = smbd_smb2_request_check_session(req);
1964 x = req->session;
1965 if (x != NULL) {
1966 signing_required = x->global->signing_required;
1967 encryption_required = x->global->encryption_required;
1969 if (opcode == SMB2_OP_SESSSETUP &&
1970 x->global->channels[0].signing_key.length) {
1971 signing_required = true;
1975 req->do_signing = false;
1976 req->do_encryption = false;
1977 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1978 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1979 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1981 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1982 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1983 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1984 (unsigned long long)x->global->session_wire_id,
1985 (unsigned long long)tf_session_id));
1987 * TODO: windows allows this...
1988 * should we drop the connection?
1990 * For now we just return ACCESS_DENIED
1991 * (Windows clients never trigger this)
1992 * and wait for an update of [MS-SMB2].
1994 return smbd_smb2_request_error(req,
1995 NT_STATUS_ACCESS_DENIED);
1998 req->do_encryption = true;
2001 if (encryption_required && !req->do_encryption) {
2002 return smbd_smb2_request_error(req,
2003 NT_STATUS_ACCESS_DENIED);
2006 call = smbd_smb2_call(opcode);
2007 if (call == NULL) {
2008 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2011 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2012 SMB2_HDR_FLAG_SIGNED |
2013 SMB2_HDR_FLAG_DFS;
2014 if (opcode == SMB2_OP_CANCEL) {
2015 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2017 if ((flags & ~allowed_flags) != 0) {
2018 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2021 if (flags & SMB2_HDR_FLAG_CHAINED) {
2023 * This check is mostly for giving the correct error code
2024 * for compounded requests.
2026 if (!NT_STATUS_IS_OK(session_status)) {
2027 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2029 } else {
2030 req->compat_chain_fsp = NULL;
2033 if (req->do_encryption) {
2034 signing_required = false;
2035 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2036 DATA_BLOB signing_key;
2038 if (x == NULL) {
2040 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2041 * If the SMB2 header of the SMB2 NEGOTIATE
2042 * request has the SMB2_FLAGS_SIGNED bit set in the
2043 * Flags field, the server MUST fail the request
2044 * with STATUS_INVALID_PARAMETER.
2046 * Microsoft test tool checks this.
2049 if ((opcode == SMB2_OP_NEGPROT) &&
2050 (flags & SMB2_HDR_FLAG_SIGNED)) {
2051 status = NT_STATUS_INVALID_PARAMETER;
2052 } else {
2053 status = NT_STATUS_USER_SESSION_DELETED;
2055 return smbd_smb2_request_error(req, status);
2058 signing_key = x->global->channels[0].signing_key;
2061 * If we have a signing key, we should
2062 * sign the response
2064 if (signing_key.length > 0) {
2065 req->do_signing = true;
2068 status = smb2_signing_check_pdu(signing_key,
2069 conn->protocol,
2070 SMBD_SMB2_IN_HDR_IOV(req),
2071 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2072 if (!NT_STATUS_IS_OK(status)) {
2073 return smbd_smb2_request_error(req, status);
2077 * Now that we know the request was correctly signed
2078 * we have to sign the response too.
2080 req->do_signing = true;
2082 if (!NT_STATUS_IS_OK(session_status)) {
2083 return smbd_smb2_request_error(req, session_status);
2085 } else if (opcode == SMB2_OP_CANCEL) {
2086 /* Cancel requests are allowed to skip the signing */
2087 } else if (signing_required) {
2089 * If signing is required we try to sign
2090 * a possible error response
2092 req->do_signing = true;
2093 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2096 if (flags & SMB2_HDR_FLAG_CHAINED) {
2097 req->compound_related = true;
2100 if (call->need_session) {
2101 if (!NT_STATUS_IS_OK(session_status)) {
2102 return smbd_smb2_request_error(req, session_status);
2106 if (call->need_tcon) {
2107 SMB_ASSERT(call->need_session);
2110 * This call needs to be run as user.
2112 * smbd_smb2_request_check_tcon()
2113 * calls change_to_user() on success.
2115 status = smbd_smb2_request_check_tcon(req);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 return smbd_smb2_request_error(req, status);
2119 if (req->tcon->global->encryption_required) {
2120 encryption_required = true;
2122 if (encryption_required && !req->do_encryption) {
2123 return smbd_smb2_request_error(req,
2124 NT_STATUS_ACCESS_DENIED);
2128 if (call->fileid_ofs != 0) {
2129 size_t needed = call->fileid_ofs + 16;
2130 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2131 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2132 uint64_t file_id_persistent;
2133 uint64_t file_id_volatile;
2134 struct files_struct *fsp;
2136 SMB_ASSERT(call->need_tcon);
2138 if (needed > body_size) {
2139 return smbd_smb2_request_error(req,
2140 NT_STATUS_INVALID_PARAMETER);
2143 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2144 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2146 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2147 if (fsp == NULL) {
2148 if (!call->allow_invalid_fileid) {
2149 return smbd_smb2_request_error(req,
2150 NT_STATUS_FILE_CLOSED);
2153 if (file_id_persistent != UINT64_MAX) {
2154 return smbd_smb2_request_error(req,
2155 NT_STATUS_FILE_CLOSED);
2157 if (file_id_volatile != UINT64_MAX) {
2158 return smbd_smb2_request_error(req,
2159 NT_STATUS_FILE_CLOSED);
2164 if (call->as_root) {
2165 SMB_ASSERT(call->fileid_ofs == 0);
2166 /* This call needs to be run as root */
2167 change_to_root_user();
2168 } else {
2169 SMB_ASSERT(call->need_tcon);
2172 switch (opcode) {
2173 case SMB2_OP_NEGPROT:
2175 START_PROFILE(smb2_negprot);
2176 return_value = smbd_smb2_request_process_negprot(req);
2177 END_PROFILE(smb2_negprot);
2179 break;
2181 case SMB2_OP_SESSSETUP:
2183 START_PROFILE(smb2_sesssetup);
2184 return_value = smbd_smb2_request_process_sesssetup(req);
2185 END_PROFILE(smb2_sesssetup);
2187 break;
2189 case SMB2_OP_LOGOFF:
2191 START_PROFILE(smb2_logoff);
2192 return_value = smbd_smb2_request_process_logoff(req);
2193 END_PROFILE(smb2_logoff);
2195 break;
2197 case SMB2_OP_TCON:
2199 START_PROFILE(smb2_tcon);
2200 return_value = smbd_smb2_request_process_tcon(req);
2201 END_PROFILE(smb2_tcon);
2203 break;
2205 case SMB2_OP_TDIS:
2207 START_PROFILE(smb2_tdis);
2208 return_value = smbd_smb2_request_process_tdis(req);
2209 END_PROFILE(smb2_tdis);
2211 break;
2213 case SMB2_OP_CREATE:
2215 START_PROFILE(smb2_create);
2216 return_value = smbd_smb2_request_process_create(req);
2217 END_PROFILE(smb2_create);
2219 break;
2221 case SMB2_OP_CLOSE:
2223 START_PROFILE(smb2_close);
2224 return_value = smbd_smb2_request_process_close(req);
2225 END_PROFILE(smb2_close);
2227 break;
2229 case SMB2_OP_FLUSH:
2231 START_PROFILE(smb2_flush);
2232 return_value = smbd_smb2_request_process_flush(req);
2233 END_PROFILE(smb2_flush);
2235 break;
2237 case SMB2_OP_READ:
2239 START_PROFILE(smb2_read);
2240 return_value = smbd_smb2_request_process_read(req);
2241 END_PROFILE(smb2_read);
2243 break;
2245 case SMB2_OP_WRITE:
2247 START_PROFILE(smb2_write);
2248 return_value = smbd_smb2_request_process_write(req);
2249 END_PROFILE(smb2_write);
2251 break;
2253 case SMB2_OP_LOCK:
2255 START_PROFILE(smb2_lock);
2256 return_value = smbd_smb2_request_process_lock(req);
2257 END_PROFILE(smb2_lock);
2259 break;
2261 case SMB2_OP_IOCTL:
2263 START_PROFILE(smb2_ioctl);
2264 return_value = smbd_smb2_request_process_ioctl(req);
2265 END_PROFILE(smb2_ioctl);
2267 break;
2269 case SMB2_OP_CANCEL:
2271 START_PROFILE(smb2_cancel);
2272 return_value = smbd_smb2_request_process_cancel(req);
2273 END_PROFILE(smb2_cancel);
2275 break;
2277 case SMB2_OP_KEEPALIVE:
2279 START_PROFILE(smb2_keepalive);
2280 return_value = smbd_smb2_request_process_keepalive(req);
2281 END_PROFILE(smb2_keepalive);
2283 break;
2285 case SMB2_OP_FIND:
2287 START_PROFILE(smb2_find);
2288 return_value = smbd_smb2_request_process_find(req);
2289 END_PROFILE(smb2_find);
2291 break;
2293 case SMB2_OP_NOTIFY:
2295 START_PROFILE(smb2_notify);
2296 return_value = smbd_smb2_request_process_notify(req);
2297 END_PROFILE(smb2_notify);
2299 break;
2301 case SMB2_OP_GETINFO:
2303 START_PROFILE(smb2_getinfo);
2304 return_value = smbd_smb2_request_process_getinfo(req);
2305 END_PROFILE(smb2_getinfo);
2307 break;
2309 case SMB2_OP_SETINFO:
2311 START_PROFILE(smb2_setinfo);
2312 return_value = smbd_smb2_request_process_setinfo(req);
2313 END_PROFILE(smb2_setinfo);
2315 break;
2317 case SMB2_OP_BREAK:
2319 START_PROFILE(smb2_break);
2320 return_value = smbd_smb2_request_process_break(req);
2321 END_PROFILE(smb2_break);
2323 break;
2325 default:
2326 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2327 break;
2329 return return_value;
2332 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2334 struct smbd_server_connection *sconn = req->sconn;
2335 struct smbXsrv_connection *conn = req->sconn->conn;
2336 int first_idx = 1;
2337 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2338 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2339 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2340 NTSTATUS status;
2342 req->subreq = NULL;
2343 TALLOC_FREE(req->async_te);
2345 if (req->do_encryption &&
2346 (firsttf->iov_len == 0) &&
2347 (req->first_key.length == 0) &&
2348 (req->session != NULL) &&
2349 (req->session->global->encryption_key.length != 0))
2351 DATA_BLOB encryption_key = req->session->global->encryption_key;
2352 uint8_t *tf;
2353 uint64_t session_id = req->session->global->session_wire_id;
2354 struct smbXsrv_session *x = req->session;
2355 uint64_t nonce_high;
2356 uint64_t nonce_low;
2358 nonce_high = x->nonce_high;
2359 nonce_low = x->nonce_low;
2361 x->nonce_low += 1;
2362 if (x->nonce_low == 0) {
2363 x->nonce_low += 1;
2364 x->nonce_high += 1;
2368 * We need to place the SMB2_TRANSFORM header before the
2369 * first SMB2 header
2373 * we need to remember the encryption key
2374 * and defer the signing/encryption until
2375 * we are sure that we do not change
2376 * the header again.
2378 req->first_key = data_blob_dup_talloc(req, encryption_key);
2379 if (req->first_key.data == NULL) {
2380 return NT_STATUS_NO_MEMORY;
2383 tf = talloc_zero_array(req, uint8_t,
2384 SMB2_TF_HDR_SIZE);
2385 if (tf == NULL) {
2386 return NT_STATUS_NO_MEMORY;
2389 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2390 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2391 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2392 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2394 firsttf->iov_base = (void *)tf;
2395 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2398 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2399 (req->last_key.length > 0) &&
2400 (firsttf->iov_len == 0))
2402 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2403 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2406 * As we are sure the header of the last request in the
2407 * compound chain will not change, we can to sign here
2408 * with the last signing key we remembered.
2410 status = smb2_signing_sign_pdu(req->last_key,
2411 conn->protocol,
2412 lasthdr,
2413 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2414 if (!NT_STATUS_IS_OK(status)) {
2415 return status;
2418 if (req->last_key.length > 0) {
2419 data_blob_clear_free(&req->last_key);
2422 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2424 if (req->current_idx < req->out.vector_count) {
2426 * We must process the remaining compound
2427 * SMB2 requests before any new incoming SMB2
2428 * requests. This is because incoming SMB2
2429 * requests may include a cancel for a
2430 * compound request we haven't processed
2431 * yet.
2433 struct tevent_immediate *im = tevent_create_immediate(req);
2434 if (!im) {
2435 return NT_STATUS_NO_MEMORY;
2438 if (req->do_signing && firsttf->iov_len == 0) {
2439 struct smbXsrv_session *x = req->session;
2440 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2443 * we need to remember the signing key
2444 * and defer the signing until
2445 * we are sure that we do not change
2446 * the header again.
2448 req->last_key = data_blob_dup_talloc(req, signing_key);
2449 if (req->last_key.data == NULL) {
2450 return NT_STATUS_NO_MEMORY;
2454 tevent_schedule_immediate(im,
2455 req->sconn->ev_ctx,
2456 smbd_smb2_request_dispatch_immediate,
2457 req);
2458 return NT_STATUS_OK;
2461 if (req->compound_related) {
2462 req->compound_related = false;
2465 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2467 /* Set credit for these operations (zero credits if this
2468 is a final reply for an async operation). */
2469 smb2_calculate_credits(req, req);
2472 * now check if we need to sign the current response
2474 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2475 status = smb2_signing_encrypt_pdu(req->first_key,
2476 conn->protocol,
2477 firsttf,
2478 req->out.vector_count - first_idx);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 return status;
2482 } else if (req->do_signing) {
2483 struct smbXsrv_session *x = req->session;
2484 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2486 status = smb2_signing_sign_pdu(signing_key,
2487 conn->protocol,
2488 outhdr,
2489 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 return status;
2494 if (req->first_key.length > 0) {
2495 data_blob_clear_free(&req->first_key);
2498 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2499 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2500 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2501 /* Dynamic part is NULL. Chop it off,
2502 We're going to send it via sendfile. */
2503 req->out.vector_count -= 1;
2507 * We're done with this request -
2508 * move it off the "being processed" queue.
2510 DLIST_REMOVE(req->sconn->smb2.requests, req);
2512 req->queue_entry.mem_ctx = req;
2513 req->queue_entry.vector = req->out.vector;
2514 req->queue_entry.count = req->out.vector_count;
2515 DLIST_ADD_END(req->sconn->smb2.send_queue, &req->queue_entry, NULL);
2516 req->sconn->smb2.send_queue_len++;
2518 status = smbd_smb2_flush_send_queue(sconn);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 return status;
2523 return NT_STATUS_OK;
2526 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2528 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2529 struct tevent_immediate *im,
2530 void *private_data)
2532 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2533 struct smbd_smb2_request);
2534 struct smbd_server_connection *sconn = req->sconn;
2535 NTSTATUS status;
2537 TALLOC_FREE(im);
2539 if (DEBUGLEVEL >= 10) {
2540 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2541 req->current_idx, req->in.vector_count));
2542 print_req_vectors(req);
2545 status = smbd_smb2_request_dispatch(req);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 smbd_server_connection_terminate(sconn, nt_errstr(status));
2548 return;
2551 status = smbd_smb2_request_next_incoming(sconn);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554 return;
2558 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2559 NTSTATUS status,
2560 DATA_BLOB body, DATA_BLOB *dyn,
2561 const char *location)
2563 uint8_t *outhdr;
2564 struct iovec *outbody_v;
2565 struct iovec *outdyn_v;
2566 uint32_t next_command_ofs;
2568 DEBUG(10,("smbd_smb2_request_done_ex: "
2569 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2570 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2571 dyn ? "yes": "no",
2572 (unsigned int)(dyn ? dyn->length : 0),
2573 location));
2575 if (body.length < 2) {
2576 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2579 if ((body.length % 2) != 0) {
2580 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2583 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2584 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2585 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2587 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2588 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2590 outbody_v->iov_base = (void *)body.data;
2591 outbody_v->iov_len = body.length;
2593 if (dyn) {
2594 outdyn_v->iov_base = (void *)dyn->data;
2595 outdyn_v->iov_len = dyn->length;
2596 } else {
2597 outdyn_v->iov_base = NULL;
2598 outdyn_v->iov_len = 0;
2601 /* see if we need to recalculate the offset to the next response */
2602 if (next_command_ofs > 0) {
2603 next_command_ofs = SMB2_HDR_BODY;
2604 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2605 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2608 if ((next_command_ofs % 8) != 0) {
2609 size_t pad_size = 8 - (next_command_ofs % 8);
2610 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2612 * if the dyn buffer is empty
2613 * we can use it to add padding
2615 uint8_t *pad;
2617 pad = talloc_zero_array(req,
2618 uint8_t, pad_size);
2619 if (pad == NULL) {
2620 return smbd_smb2_request_error(req,
2621 NT_STATUS_NO_MEMORY);
2624 outdyn_v->iov_base = (void *)pad;
2625 outdyn_v->iov_len = pad_size;
2626 } else {
2628 * For now we copy the dynamic buffer
2629 * and add the padding to the new buffer
2631 size_t old_size;
2632 uint8_t *old_dyn;
2633 size_t new_size;
2634 uint8_t *new_dyn;
2636 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2637 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2639 new_size = old_size + pad_size;
2640 new_dyn = talloc_zero_array(req,
2641 uint8_t, new_size);
2642 if (new_dyn == NULL) {
2643 return smbd_smb2_request_error(req,
2644 NT_STATUS_NO_MEMORY);
2647 memcpy(new_dyn, old_dyn, old_size);
2648 memset(new_dyn + old_size, 0, pad_size);
2650 outdyn_v->iov_base = (void *)new_dyn;
2651 outdyn_v->iov_len = new_size;
2653 next_command_ofs += pad_size;
2656 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2658 return smbd_smb2_request_reply(req);
2661 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2662 NTSTATUS status,
2663 DATA_BLOB *info,
2664 const char *location)
2666 struct smbXsrv_connection *xconn = req->sconn->conn;
2667 DATA_BLOB body;
2668 DATA_BLOB _dyn;
2669 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2670 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2672 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2673 req->current_idx, nt_errstr(status), info ? " +info" : "",
2674 location));
2676 if (unread_bytes) {
2677 /* Recvfile error. Drain incoming socket. */
2678 size_t ret;
2680 errno = 0;
2681 ret = drain_socket(xconn->transport.sock, unread_bytes);
2682 if (ret != unread_bytes) {
2683 NTSTATUS error;
2685 if (errno == 0) {
2686 error = NT_STATUS_IO_DEVICE_ERROR;
2687 } else {
2688 error = map_nt_error_from_unix_common(errno);
2691 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2692 "ret[%u] errno[%d] => %s\n",
2693 (unsigned)unread_bytes,
2694 (unsigned)ret, errno, nt_errstr(error)));
2695 return error;
2699 body.data = outhdr + SMB2_HDR_BODY;
2700 body.length = 8;
2701 SSVAL(body.data, 0, 9);
2703 if (info) {
2704 SIVAL(body.data, 0x04, info->length);
2705 } else {
2706 /* Allocated size of req->out.vector[i].iov_base
2707 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2708 * 1 byte without having to do an alloc.
2710 info = &_dyn;
2711 info->data = ((uint8_t *)outhdr) +
2712 OUTVEC_ALLOC_SIZE - 1;
2713 info->length = 1;
2714 SCVAL(info->data, 0, 0);
2718 * Note: Even if there is an error, continue to process the request.
2719 * per MS-SMB2.
2722 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2726 struct smbd_smb2_send_break_state {
2727 struct smbd_server_connection *sconn;
2728 struct smbd_smb2_send_queue queue_entry;
2729 uint8_t nbt_hdr[NBT_HDR_SIZE];
2730 uint8_t tf[SMB2_TF_HDR_SIZE];
2731 uint8_t hdr[SMB2_HDR_BODY];
2732 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2733 uint8_t body[1];
2736 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2737 struct smbXsrv_session *session,
2738 struct smbXsrv_tcon *tcon,
2739 const uint8_t *body,
2740 size_t body_len)
2742 struct smbd_smb2_send_break_state *state;
2743 struct smbXsrv_connection *conn = sconn->conn;
2744 bool do_encryption = session->global->encryption_required;
2745 uint64_t nonce_high = 0;
2746 uint64_t nonce_low = 0;
2747 NTSTATUS status;
2748 size_t statelen;
2750 if (tcon->global->encryption_required) {
2751 do_encryption = true;
2754 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2755 body_len;
2757 state = talloc_zero_size(sconn, statelen);
2758 if (state == NULL) {
2759 return NT_STATUS_NO_MEMORY;
2761 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2762 state->sconn = sconn;
2764 if (do_encryption) {
2765 nonce_high = session->nonce_high;
2766 nonce_low = session->nonce_low;
2768 session->nonce_low += 1;
2769 if (session->nonce_low == 0) {
2770 session->nonce_low += 1;
2771 session->nonce_high += 1;
2775 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2776 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2777 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2778 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2780 SIVAL(state->hdr, 0, SMB2_MAGIC);
2781 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2782 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2783 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2784 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2785 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2786 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2787 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2788 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2789 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2790 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2791 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2792 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2794 state->vector[0] = (struct iovec) {
2795 .iov_base = state->nbt_hdr,
2796 .iov_len = sizeof(state->nbt_hdr)
2799 if (do_encryption) {
2800 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2801 .iov_base = state->tf,
2802 .iov_len = sizeof(state->tf)
2804 } else {
2805 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2806 .iov_base = NULL,
2807 .iov_len = 0
2811 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2812 .iov_base = state->hdr,
2813 .iov_len = sizeof(state->hdr)
2816 memcpy(state->body, body, body_len);
2818 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2819 .iov_base = state->body,
2820 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2824 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2827 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2829 if (do_encryption) {
2830 DATA_BLOB encryption_key = session->global->encryption_key;
2832 status = smb2_signing_encrypt_pdu(encryption_key,
2833 conn->protocol,
2834 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2835 SMBD_SMB2_NUM_IOV_PER_REQ);
2836 if (!NT_STATUS_IS_OK(status)) {
2837 return status;
2841 state->queue_entry.mem_ctx = state;
2842 state->queue_entry.vector = state->vector;
2843 state->queue_entry.count = ARRAY_SIZE(state->vector);
2844 DLIST_ADD_END(state->sconn->smb2.send_queue, &state->queue_entry, NULL);
2845 state->sconn->smb2.send_queue_len++;
2847 status = smbd_smb2_flush_send_queue(sconn);
2848 if (!NT_STATUS_IS_OK(status)) {
2849 return status;
2852 return NT_STATUS_OK;
2855 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2856 struct smbXsrv_session *session,
2857 struct smbXsrv_tcon *tcon,
2858 struct smbXsrv_open *op,
2859 uint8_t oplock_level)
2861 uint8_t body[0x18];
2863 SSVAL(body, 0x00, sizeof(body));
2864 SCVAL(body, 0x02, oplock_level);
2865 SCVAL(body, 0x03, 0); /* reserved */
2866 SIVAL(body, 0x04, 0); /* reserved */
2867 SBVAL(body, 0x08, op->global->open_persistent_id);
2868 SBVAL(body, 0x10, op->global->open_volatile_id);
2870 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2873 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2875 NTSTATUS status;
2876 uint32_t flags;
2877 uint64_t file_id_persistent;
2878 uint64_t file_id_volatile;
2879 struct smbXsrv_open *op = NULL;
2880 struct files_struct *fsp = NULL;
2881 const uint8_t *body = NULL;
2884 * This is only called with a pktbuf
2885 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2886 * bytes
2889 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2890 /* Transform header. Cannot recvfile. */
2891 return false;
2893 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2894 /* Not SMB2. Normal error path will cope. */
2895 return false;
2897 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2898 /* Not SMB2. Normal error path will cope. */
2899 return false;
2901 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2902 /* Needs to be a WRITE. */
2903 return false;
2905 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2906 /* Chained. Cannot recvfile. */
2907 return false;
2909 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2910 if (flags & SMB2_HDR_FLAG_CHAINED) {
2911 /* Chained. Cannot recvfile. */
2912 return false;
2914 if (flags & SMB2_HDR_FLAG_SIGNED) {
2915 /* Signed. Cannot recvfile. */
2916 return false;
2919 body = &state->pktbuf[SMB2_HDR_BODY];
2921 file_id_persistent = BVAL(body, 0x10);
2922 file_id_volatile = BVAL(body, 0x18);
2924 status = smb2srv_open_lookup(state->req->sconn->conn,
2925 file_id_persistent,
2926 file_id_volatile,
2927 0, /* now */
2928 &op);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 return false;
2933 fsp = op->compat;
2934 if (fsp == NULL) {
2935 return false;
2937 if (fsp->conn == NULL) {
2938 return false;
2941 if (IS_IPC(fsp->conn)) {
2942 return false;
2944 if (IS_PRINT(fsp->conn)) {
2945 return false;
2948 DEBUG(10,("Doing recvfile write len = %u\n",
2949 (unsigned int)(state->pktfull - state->pktlen)));
2951 return true;
2954 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2956 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
2957 struct smbXsrv_connection *xconn = sconn->conn;
2958 size_t max_send_queue_len;
2959 size_t cur_send_queue_len;
2961 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2963 * we're not supposed to do any io
2965 return NT_STATUS_OK;
2968 if (state->req != NULL) {
2970 * if there is already a tstream_readv_pdu
2971 * pending, we are done.
2973 return NT_STATUS_OK;
2976 max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
2977 cur_send_queue_len = sconn->smb2.send_queue_len;
2979 if (cur_send_queue_len > max_send_queue_len) {
2981 * if we have a lot of requests to send,
2982 * we wait until they are on the wire until we
2983 * ask for the next request.
2985 return NT_STATUS_OK;
2988 /* ask for the next request */
2989 ZERO_STRUCTP(state);
2990 state->req = smbd_smb2_request_allocate(sconn);
2991 if (state->req == NULL) {
2992 return NT_STATUS_NO_MEMORY;
2994 state->req->sconn = sconn;
2995 state->min_recv_size = lp_min_receive_file_size();
2997 TEVENT_FD_READABLE(sconn->smb2.fde);
2999 return NT_STATUS_OK;
3002 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3003 uint8_t *inbuf, size_t size)
3005 NTSTATUS status;
3006 struct smbd_smb2_request *req = NULL;
3008 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3009 (unsigned int)size));
3011 status = smbd_initialize_smb2(sconn);
3012 if (!NT_STATUS_IS_OK(status)) {
3013 smbd_server_connection_terminate(sconn, nt_errstr(status));
3014 return;
3017 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3018 if (!NT_STATUS_IS_OK(status)) {
3019 smbd_server_connection_terminate(sconn, nt_errstr(status));
3020 return;
3023 status = smbd_smb2_request_validate(req);
3024 if (!NT_STATUS_IS_OK(status)) {
3025 smbd_server_connection_terminate(sconn, nt_errstr(status));
3026 return;
3029 status = smbd_smb2_request_setup_out(req);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 smbd_server_connection_terminate(sconn, nt_errstr(status));
3032 return;
3035 status = smbd_smb2_request_dispatch(req);
3036 if (!NT_STATUS_IS_OK(status)) {
3037 smbd_server_connection_terminate(sconn, nt_errstr(status));
3038 return;
3041 status = smbd_smb2_request_next_incoming(sconn);
3042 if (!NT_STATUS_IS_OK(status)) {
3043 smbd_server_connection_terminate(sconn, nt_errstr(status));
3044 return;
3047 sconn->num_requests++;
3050 static int socket_error_from_errno(int ret,
3051 int sys_errno,
3052 bool *retry)
3054 *retry = false;
3056 if (ret >= 0) {
3057 return 0;
3060 if (ret != -1) {
3061 return EIO;
3064 if (sys_errno == 0) {
3065 return EIO;
3068 if (sys_errno == EINTR) {
3069 *retry = true;
3070 return sys_errno;
3073 if (sys_errno == EINPROGRESS) {
3074 *retry = true;
3075 return sys_errno;
3078 if (sys_errno == EAGAIN) {
3079 *retry = true;
3080 return sys_errno;
3083 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3084 if (sys_errno == ENOMEM) {
3085 *retry = true;
3086 return sys_errno;
3089 #ifdef EWOULDBLOCK
3090 #if EWOULDBLOCK != EAGAIN
3091 if (sys_errno == EWOULDBLOCK) {
3092 *retry = true;
3093 return sys_errno;
3095 #endif
3096 #endif
3098 return sys_errno;
3101 static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
3103 struct smbXsrv_connection *xconn = sconn->conn;
3104 int ret;
3105 int err;
3106 bool retry;
3108 if (sconn->smb2.send_queue == NULL) {
3109 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3110 return NT_STATUS_OK;
3113 while (sconn->smb2.send_queue != NULL) {
3114 struct smbd_smb2_send_queue *e = sconn->smb2.send_queue;
3116 if (e->sendfile_header != NULL) {
3117 size_t size = 0;
3118 size_t i = 0;
3119 uint8_t *buf;
3121 for (i=0; i < e->count; i++) {
3122 size += e->vector[i].iov_len;
3125 if (size <= e->sendfile_header->length) {
3126 buf = e->sendfile_header->data;
3127 } else {
3128 buf = talloc_array(e->mem_ctx, uint8_t, size);
3129 if (buf == NULL) {
3130 return NT_STATUS_NO_MEMORY;
3134 size = 0;
3135 for (i=0; i < e->count; i++) {
3136 memcpy(buf+size,
3137 e->vector[i].iov_base,
3138 e->vector[i].iov_len);
3139 size += e->vector[i].iov_len;
3142 e->sendfile_header->data = buf;
3143 e->sendfile_header->length = size;
3144 e->count = 0;
3146 sconn->smb2.send_queue_len--;
3147 DLIST_REMOVE(sconn->smb2.send_queue, e);
3149 * This triggers the sendfile path via
3150 * the destructor.
3152 talloc_free(e->mem_ctx);
3153 continue;
3156 ret = writev(xconn->transport.sock, e->vector, e->count);
3157 if (ret == 0) {
3158 /* propagate end of file */
3159 return NT_STATUS_INTERNAL_ERROR;
3161 err = socket_error_from_errno(ret, errno, &retry);
3162 if (retry) {
3163 /* retry later */
3164 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3165 return NT_STATUS_OK;
3167 if (err != 0) {
3168 return map_nt_error_from_unix_common(err);
3170 while (ret > 0) {
3171 if (ret < e->vector[0].iov_len) {
3172 uint8_t *base;
3173 base = (uint8_t *)e->vector[0].iov_base;
3174 base += ret;
3175 e->vector[0].iov_base = (void *)base;
3176 e->vector[0].iov_len -= ret;
3177 break;
3179 ret -= e->vector[0].iov_len;
3180 e->vector += 1;
3181 e->count -= 1;
3185 * there're maybe some empty vectors at the end
3186 * which we need to skip, otherwise we would get
3187 * ret == 0 from the readv() call and return EPIPE
3189 while (e->count > 0) {
3190 if (e->vector[0].iov_len > 0) {
3191 break;
3193 e->vector += 1;
3194 e->count -= 1;
3197 if (e->count > 0) {
3198 /* we have more to write */
3199 TEVENT_FD_WRITEABLE(sconn->smb2.fde);
3200 return NT_STATUS_OK;
3203 sconn->smb2.send_queue_len--;
3204 DLIST_REMOVE(sconn->smb2.send_queue, e);
3205 talloc_free(e->mem_ctx);
3208 return NT_STATUS_OK;
3211 static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn,
3212 uint16_t fde_flags)
3214 struct smbXsrv_connection *xconn = sconn->conn;
3215 struct smbd_smb2_request_read_state *state = &sconn->smb2.request_read_state;
3216 struct smbd_smb2_request *req = NULL;
3217 size_t min_recvfile_size = UINT32_MAX;
3218 int ret;
3219 int err;
3220 bool retry;
3221 NTSTATUS status;
3222 NTTIME now;
3224 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3226 * we're not supposed to do any io
3228 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3229 TEVENT_FD_NOT_WRITEABLE(sconn->smb2.fde);
3230 return NT_STATUS_OK;
3233 if (fde_flags & TEVENT_FD_WRITE) {
3234 status = smbd_smb2_flush_send_queue(sconn);
3235 if (!NT_STATUS_IS_OK(status)) {
3236 return status;
3240 if (!(fde_flags & TEVENT_FD_READ)) {
3241 return NT_STATUS_OK;
3244 if (state->req == NULL) {
3245 TEVENT_FD_NOT_READABLE(sconn->smb2.fde);
3246 return NT_STATUS_OK;
3249 again:
3250 if (!state->hdr.done) {
3251 state->hdr.done = true;
3253 state->vector.iov_base = (void *)state->hdr.nbt;
3254 state->vector.iov_len = NBT_HDR_SIZE;
3257 ret = readv(xconn->transport.sock, &state->vector, 1);
3258 if (ret == 0) {
3259 /* propagate end of file */
3260 return NT_STATUS_END_OF_FILE;
3262 err = socket_error_from_errno(ret, errno, &retry);
3263 if (retry) {
3264 /* retry later */
3265 TEVENT_FD_READABLE(sconn->smb2.fde);
3266 return NT_STATUS_OK;
3268 if (err != 0) {
3269 return map_nt_error_from_unix_common(err);
3272 if (ret < state->vector.iov_len) {
3273 uint8_t *base;
3274 base = (uint8_t *)state->vector.iov_base;
3275 base += ret;
3276 state->vector.iov_base = (void *)base;
3277 state->vector.iov_len -= ret;
3278 /* we have more to read */
3279 TEVENT_FD_READABLE(sconn->smb2.fde);
3280 return NT_STATUS_OK;
3283 if (state->pktlen > 0) {
3284 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3286 * Not a possible receivefile write.
3287 * Read the rest of the data.
3289 state->doing_receivefile = false;
3291 state->pktbuf = talloc_realloc(state->req,
3292 state->pktbuf,
3293 uint8_t,
3294 state->pktfull);
3295 if (state->pktbuf == NULL) {
3296 return NT_STATUS_NO_MEMORY;
3299 state->vector.iov_base = (void *)(state->pktbuf +
3300 state->pktlen);
3301 state->vector.iov_len = (state->pktfull -
3302 state->pktlen);
3304 state->pktlen = state->pktfull;
3305 goto again;
3309 * Either this is a receivefile write so we've
3310 * done a short read, or if not we have all the data.
3312 goto got_full;
3316 * Now we analyze the NBT header
3318 if (state->hdr.nbt[0] != 0x00) {
3319 state->min_recv_size = 0;
3321 state->pktfull = smb2_len(state->hdr.nbt);
3322 if (state->pktfull == 0) {
3323 goto got_full;
3326 if (state->min_recv_size != 0) {
3327 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3328 min_recvfile_size += state->min_recv_size;
3331 if (state->pktfull > min_recvfile_size) {
3333 * Might be a receivefile write. Read the SMB2 HEADER +
3334 * SMB2_WRITE header first. Set 'doing_receivefile'
3335 * as we're *attempting* receivefile write. If this
3336 * turns out not to be a SMB2_WRITE request or otherwise
3337 * not suitable then we'll just read the rest of the data
3338 * the next time this function is called.
3340 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3341 state->doing_receivefile = true;
3342 } else {
3343 state->pktlen = state->pktfull;
3346 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3347 if (state->pktbuf == NULL) {
3348 return NT_STATUS_NO_MEMORY;
3351 state->vector.iov_base = (void *)state->pktbuf;
3352 state->vector.iov_len = state->pktlen;
3354 goto again;
3356 got_full:
3358 if (state->hdr.nbt[0] != 0x00) {
3359 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3360 state->hdr.nbt[0]));
3362 req = state->req;
3363 ZERO_STRUCTP(state);
3364 state->req = req;
3365 state->min_recv_size = lp_min_receive_file_size();
3366 req = NULL;
3367 goto again;
3370 req = state->req;
3371 state->req = NULL;
3373 req->request_time = timeval_current();
3374 now = timeval_to_nttime(&req->request_time);
3376 status = smbd_smb2_inbuf_parse_compound(req->sconn->conn,
3377 now,
3378 state->pktbuf,
3379 state->pktlen,
3380 req,
3381 &req->in.vector,
3382 &req->in.vector_count);
3383 if (!NT_STATUS_IS_OK(status)) {
3384 return status;
3387 if (state->doing_receivefile) {
3388 req->smb1req = talloc_zero(req, struct smb_request);
3389 if (req->smb1req == NULL) {
3390 return NT_STATUS_NO_MEMORY;
3392 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3395 ZERO_STRUCTP(state);
3397 req->current_idx = 1;
3399 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3400 req->current_idx, req->in.vector_count));
3402 status = smbd_smb2_request_validate(req);
3403 if (!NT_STATUS_IS_OK(status)) {
3404 return status;
3407 status = smbd_smb2_request_setup_out(req);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 return status;
3412 status = smbd_smb2_request_dispatch(req);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 return status;
3417 sconn->num_requests++;
3419 /* The timeout_processing function isn't run nearly
3420 often enough to implement 'max log size' without
3421 overrunning the size of the file by many megabytes.
3422 This is especially true if we are running at debug
3423 level 10. Checking every 50 SMB2s is a nice
3424 tradeoff of performance vs log file size overrun. */
3426 if ((sconn->num_requests % 50) == 0 &&
3427 need_to_check_log_size()) {
3428 change_to_root_user();
3429 check_log_size();
3432 status = smbd_smb2_request_next_incoming(sconn);
3433 if (!NT_STATUS_IS_OK(status)) {
3434 return status;
3437 return NT_STATUS_OK;
3440 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3441 struct tevent_fd *fde,
3442 uint16_t flags,
3443 void *private_data)
3445 struct smbd_server_connection *sconn =
3446 talloc_get_type_abort(private_data,
3447 struct smbd_server_connection);
3448 NTSTATUS status;
3450 status = smbd_smb2_io_handler(sconn, flags);
3451 if (!NT_STATUS_IS_OK(status)) {
3452 smbd_server_connection_terminate(sconn, nt_errstr(status));
3453 return;