s3:smb2_server: pass smbXsrv_connection to smb2_validate_sequence_number()
[Samba.git] / source3 / smbd / smb2_server.c
blob427f81550d960add5fe69c4e4be09001e82eb15a
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 smbXsrv_connection *xconn);
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 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 void smb2_setup_nbt_length(struct iovec *vector, int count)
243 size_t len = 0;
244 int i;
246 for (i=1; i < count; i++) {
247 len += vector[i].iov_len;
250 _smb2_setlen(vector[0].iov_base, len);
253 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
255 if (req->first_key.length > 0) {
256 data_blob_clear_free(&req->first_key);
258 if (req->last_key.length > 0) {
259 data_blob_clear_free(&req->last_key);
261 return 0;
264 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
266 TALLOC_CTX *mem_pool;
267 struct smbd_smb2_request *req;
269 #if 0
270 /* Enable this to find subtle valgrind errors. */
271 mem_pool = talloc_init("smbd_smb2_request_allocate");
272 #else
273 mem_pool = talloc_tos();
274 #endif
275 if (mem_pool == NULL) {
276 return NULL;
279 req = talloc_zero(mem_pool, struct smbd_smb2_request);
280 if (req == NULL) {
281 talloc_free(mem_pool);
282 return NULL;
284 talloc_reparent(mem_pool, mem_ctx, req);
285 #if 0
286 TALLOC_FREE(mem_pool);
287 #endif
289 req->last_session_id = UINT64_MAX;
290 req->last_tid = UINT32_MAX;
292 talloc_set_destructor(req, smbd_smb2_request_destructor);
294 return req;
297 static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
298 NTTIME now,
299 uint8_t *buf,
300 size_t buflen,
301 struct smbd_smb2_request *req,
302 struct iovec **piov,
303 int *pnum_iov)
305 TALLOC_CTX *mem_ctx = req;
306 struct iovec *iov;
307 int num_iov = 1;
308 size_t taken = 0;
309 uint8_t *first_hdr = buf;
310 size_t verified_buflen = 0;
311 uint8_t *tf = NULL;
312 size_t tf_len = 0;
315 * Note: index '0' is reserved for the transport protocol
317 iov = req->in._vector;
319 while (taken < buflen) {
320 size_t len = buflen - taken;
321 uint8_t *hdr = first_hdr + taken;
322 struct iovec *cur;
323 size_t full_size;
324 size_t next_command_ofs;
325 uint16_t body_size;
326 uint8_t *body = NULL;
327 uint32_t dyn_size;
328 uint8_t *dyn = NULL;
329 struct iovec *iov_alloc = NULL;
331 if (iov != req->in._vector) {
332 iov_alloc = iov;
335 if (verified_buflen > taken) {
336 len = verified_buflen - taken;
337 } else {
338 tf = NULL;
339 tf_len = 0;
342 if (len < 4) {
343 DEBUG(10, ("%d bytes left, expected at least %d\n",
344 (int)len, 4));
345 goto inval;
347 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
348 struct smbXsrv_session *s = NULL;
349 uint64_t uid;
350 struct iovec tf_iov[2];
351 NTSTATUS status;
352 size_t enc_len;
354 if (xconn->protocol < PROTOCOL_SMB2_24) {
355 DEBUG(10, ("Got SMB2_TRANSFORM header, "
356 "but dialect[0x%04X] is used\n",
357 xconn->smb2.server.dialect));
358 goto inval;
361 if (!(xconn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
362 DEBUG(10, ("Got SMB2_TRANSFORM header, "
363 "but not negotiated "
364 "client[0x%08X] server[0x%08X]\n",
365 xconn->smb2.client.capabilities,
366 xconn->smb2.server.capabilities));
367 goto inval;
370 if (len < SMB2_TF_HDR_SIZE) {
371 DEBUG(1, ("%d bytes left, expected at least %d\n",
372 (int)len, SMB2_TF_HDR_SIZE));
373 goto inval;
375 tf = hdr;
376 tf_len = SMB2_TF_HDR_SIZE;
377 taken += tf_len;
379 hdr = first_hdr + taken;
380 enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
381 uid = BVAL(tf, SMB2_TF_SESSION_ID);
383 if (len < SMB2_TF_HDR_SIZE + enc_len) {
384 DEBUG(1, ("%d bytes left, expected at least %d\n",
385 (int)len,
386 (int)(SMB2_TF_HDR_SIZE + enc_len)));
387 goto inval;
390 status = smb2srv_session_lookup(xconn, uid, now, &s);
391 if (s == NULL) {
392 DEBUG(1, ("invalid session[%llu] in "
393 "SMB2_TRANSFORM header\n",
394 (unsigned long long)uid));
395 TALLOC_FREE(iov_alloc);
396 return NT_STATUS_USER_SESSION_DELETED;
399 tf_iov[0].iov_base = (void *)tf;
400 tf_iov[0].iov_len = tf_len;
401 tf_iov[1].iov_base = (void *)hdr;
402 tf_iov[1].iov_len = enc_len;
404 status = smb2_signing_decrypt_pdu(s->global->decryption_key,
405 xconn->protocol,
406 tf_iov, 2);
407 if (!NT_STATUS_IS_OK(status)) {
408 TALLOC_FREE(iov_alloc);
409 return status;
412 verified_buflen = taken + enc_len;
413 len = enc_len;
417 * We need the header plus the body length field
420 if (len < SMB2_HDR_BODY + 2) {
421 DEBUG(10, ("%d bytes left, expected at least %d\n",
422 (int)len, SMB2_HDR_BODY));
423 goto inval;
425 if (IVAL(hdr, 0) != SMB2_MAGIC) {
426 DEBUG(10, ("Got non-SMB2 PDU: %x\n",
427 IVAL(hdr, 0)));
428 goto inval;
430 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
431 DEBUG(10, ("Got HDR len %d, expected %d\n",
432 SVAL(hdr, 4), SMB2_HDR_BODY));
433 goto inval;
436 full_size = len;
437 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
438 body_size = SVAL(hdr, SMB2_HDR_BODY);
440 if (next_command_ofs != 0) {
441 if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
442 goto inval;
444 if (next_command_ofs > full_size) {
445 goto inval;
447 full_size = next_command_ofs;
449 if (body_size < 2) {
450 goto inval;
452 body_size &= 0xfffe;
454 if (body_size > (full_size - SMB2_HDR_BODY)) {
456 * let the caller handle the error
458 body_size = full_size - SMB2_HDR_BODY;
460 body = hdr + SMB2_HDR_BODY;
461 dyn = body + body_size;
462 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
464 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
465 struct iovec *iov_tmp = NULL;
467 iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
468 struct iovec,
469 num_iov +
470 SMBD_SMB2_NUM_IOV_PER_REQ);
471 if (iov_tmp == NULL) {
472 TALLOC_FREE(iov_alloc);
473 return NT_STATUS_NO_MEMORY;
476 if (iov_alloc == NULL) {
477 memcpy(iov_tmp,
478 req->in._vector,
479 sizeof(req->in._vector));
482 iov = iov_tmp;
484 cur = &iov[num_iov];
485 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
487 cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
488 cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
489 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
490 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
491 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
492 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
493 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
494 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
496 taken += full_size;
499 *piov = iov;
500 *pnum_iov = num_iov;
501 return NT_STATUS_OK;
503 inval:
504 if (iov != req->in._vector) {
505 TALLOC_FREE(iov);
507 return NT_STATUS_INVALID_PARAMETER;
510 static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
511 uint8_t *inbuf, size_t size,
512 struct smbd_smb2_request **_req)
514 struct smbXsrv_connection *xconn = sconn->conn;
515 struct smbd_smb2_request *req;
516 uint32_t protocol_version;
517 const uint8_t *inhdr = NULL;
518 uint16_t cmd;
519 uint32_t next_command_ofs;
520 NTSTATUS status;
521 NTTIME now;
523 if (size < (4 + SMB2_HDR_BODY + 2)) {
524 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
525 return NT_STATUS_INVALID_PARAMETER;
528 inhdr = inbuf + 4;
530 protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
531 if (protocol_version != SMB2_MAGIC) {
532 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
533 protocol_version));
534 return NT_STATUS_INVALID_PARAMETER;
537 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
538 if (cmd != SMB2_OP_NEGPROT) {
539 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
540 cmd));
541 return NT_STATUS_INVALID_PARAMETER;
544 next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
545 if (next_command_ofs != 0) {
546 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
547 next_command_ofs));
548 return NT_STATUS_INVALID_PARAMETER;
551 req = smbd_smb2_request_allocate(xconn);
552 if (req == NULL) {
553 return NT_STATUS_NO_MEMORY;
555 req->sconn = sconn;
556 req->xconn = xconn;
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 smbXsrv_connection *xconn,
581 uint64_t message_id, uint64_t seq_id)
583 struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
584 unsigned int offset;
585 uint64_t seq_tmp;
587 seq_tmp = xconn->smb2.credits.seq_low;
588 if (seq_id < seq_tmp) {
589 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
590 "%llu (sequence id %llu) "
591 "(granted = %u, low = %llu, range = %u)\n",
592 (unsigned long long)message_id,
593 (unsigned long long)seq_id,
594 (unsigned int)xconn->smb2.credits.granted,
595 (unsigned long long)xconn->smb2.credits.seq_low,
596 (unsigned int)xconn->smb2.credits.seq_range));
597 return false;
600 seq_tmp += xconn->smb2.credits.seq_range;
601 if (seq_id >= seq_tmp) {
602 DEBUG(0,("smb2_validate_sequence_number: bad message_id "
603 "%llu (sequence id %llu) "
604 "(granted = %u, low = %llu, range = %u)\n",
605 (unsigned long long)message_id,
606 (unsigned long long)seq_id,
607 (unsigned int)xconn->smb2.credits.granted,
608 (unsigned long long)xconn->smb2.credits.seq_low,
609 (unsigned int)xconn->smb2.credits.seq_range));
610 return false;
613 offset = seq_id % xconn->smb2.credits.max;
615 if (bitmap_query(credits_bm, offset)) {
616 DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
617 "%llu (sequence id %llu) "
618 "(granted = %u, low = %llu, range = %u) "
619 "(bm offset %u)\n",
620 (unsigned long long)message_id,
621 (unsigned long long)seq_id,
622 (unsigned int)xconn->smb2.credits.granted,
623 (unsigned long long)xconn->smb2.credits.seq_low,
624 (unsigned int)xconn->smb2.credits.seq_range,
625 offset));
626 return false;
629 /* Mark the message_ids as seen in the bitmap. */
630 bitmap_set(credits_bm, offset);
632 if (seq_id != xconn->smb2.credits.seq_low) {
633 return true;
637 * Move the window forward by all the message_id's
638 * already seen.
640 while (bitmap_query(credits_bm, offset)) {
641 DEBUG(10,("smb2_validate_sequence_number: clearing "
642 "id %llu (position %u) from bitmap\n",
643 (unsigned long long)(xconn->smb2.credits.seq_low),
644 offset));
645 bitmap_clear(credits_bm, offset);
647 xconn->smb2.credits.seq_low += 1;
648 xconn->smb2.credits.seq_range -= 1;
649 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
652 return true;
655 static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
656 const uint8_t *inhdr)
658 struct smbXsrv_connection *xconn = sconn->conn;
659 uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
660 uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
661 uint16_t credit_charge = 1;
662 uint64_t i;
664 if (opcode == SMB2_OP_CANCEL) {
665 /* SMB2_CANCEL requests by definition resend messageids. */
666 return true;
669 if (xconn->smb2.credits.multicredit) {
670 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
671 credit_charge = MAX(credit_charge, 1);
674 DEBUG(11, ("smb2_validate_message_id: mid %llu (charge %llu), "
675 "credits_granted %llu, "
676 "seqnum low/range: %llu/%llu\n",
677 (unsigned long long) message_id,
678 (unsigned long long) credit_charge,
679 (unsigned long long) xconn->smb2.credits.granted,
680 (unsigned long long) xconn->smb2.credits.seq_low,
681 (unsigned long long) xconn->smb2.credits.seq_range));
683 if (xconn->smb2.credits.granted < credit_charge) {
684 DEBUG(0, ("smb2_validate_message_id: client used more "
685 "credits than granted, mid %llu, charge %llu, "
686 "credits_granted %llu, "
687 "seqnum low/range: %llu/%llu\n",
688 (unsigned long long) message_id,
689 (unsigned long long) credit_charge,
690 (unsigned long long) xconn->smb2.credits.granted,
691 (unsigned long long) xconn->smb2.credits.seq_low,
692 (unsigned long long) xconn->smb2.credits.seq_range));
693 return false;
697 * now check the message ids
699 * for multi-credit requests we need to check all current mid plus
700 * the implicit mids caused by the credit charge
701 * e.g. current mid = 15, charge 5 => mark 15-19 as used
704 for (i = 0; i <= (credit_charge-1); i++) {
705 uint64_t id = message_id + i;
706 bool ok;
708 DEBUG(11, ("Iterating mid %llu charge %u (sequence %llu)\n",
709 (unsigned long long)message_id,
710 credit_charge,
711 (unsigned long long)id));
713 ok = smb2_validate_sequence_number(xconn, message_id, id);
714 if (!ok) {
715 return false;
719 /* substract used credits */
720 xconn->smb2.credits.granted -= credit_charge;
722 return true;
725 static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
727 int count;
728 int idx;
730 count = req->in.vector_count;
732 if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
733 /* It's not a SMB2 request */
734 return NT_STATUS_INVALID_PARAMETER;
737 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
738 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
739 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
740 const uint8_t *inhdr = NULL;
742 if (hdr->iov_len != SMB2_HDR_BODY) {
743 return NT_STATUS_INVALID_PARAMETER;
746 if (body->iov_len < 2) {
747 return NT_STATUS_INVALID_PARAMETER;
750 inhdr = (const uint8_t *)hdr->iov_base;
752 /* Check the SMB2 header */
753 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
754 return NT_STATUS_INVALID_PARAMETER;
757 if (!smb2_validate_message_id(req->sconn, inhdr)) {
758 return NT_STATUS_INVALID_PARAMETER;
762 return NT_STATUS_OK;
765 static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
766 const struct iovec *in_vector,
767 struct iovec *out_vector)
769 struct smbXsrv_connection *xconn = sconn->conn;
770 const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
771 uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
772 uint16_t credit_charge = 1;
773 uint16_t credits_requested;
774 uint32_t out_flags;
775 uint16_t cmd;
776 NTSTATUS out_status;
777 uint16_t credits_granted = 0;
778 uint64_t credits_possible;
779 uint16_t current_max_credits;
782 * first we grant only 1/16th of the max range.
784 * Windows also starts with the 1/16th and then grants
785 * more later. I was only able to trigger higher
786 * values, when using a very high credit charge.
788 * TODO: scale up depending on load, free memory
789 * or other stuff.
790 * Maybe also on the relationship between number
791 * of requests and the used sequence number.
792 * Which means we would grant more credits
793 * for client which use multi credit requests.
795 current_max_credits = xconn->smb2.credits.max / 16;
796 current_max_credits = MAX(current_max_credits, 1);
798 if (xconn->smb2.credits.multicredit) {
799 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
800 credit_charge = MAX(credit_charge, 1);
803 cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
804 credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
805 out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
806 out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
808 SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
810 if (xconn->smb2.credits.max < credit_charge) {
811 smbd_server_connection_terminate(sconn,
812 "client error: credit charge > max credits\n");
813 return;
816 if (out_flags & SMB2_HDR_FLAG_ASYNC) {
818 * In case we already send an async interim
819 * response, we should not grant
820 * credits on the final response.
822 credits_granted = 0;
823 } else if (credits_requested > 0) {
824 uint16_t additional_max = 0;
825 uint16_t additional_credits = credits_requested - 1;
827 switch (cmd) {
828 case SMB2_OP_NEGPROT:
829 break;
830 case SMB2_OP_SESSSETUP:
832 * Windows 2012 RC1 starts to grant
833 * additional credits
834 * with a successful session setup
836 if (NT_STATUS_IS_OK(out_status)) {
837 additional_max = 32;
839 break;
840 default:
842 * We match windows and only grant additional credits
843 * in chunks of 32.
845 additional_max = 32;
846 break;
849 additional_credits = MIN(additional_credits, additional_max);
851 credits_granted = credit_charge + additional_credits;
852 } else if (xconn->smb2.credits.granted == 0) {
854 * Make sure the client has always at least one credit
856 credits_granted = 1;
860 * sequence numbers should not wrap
862 * 1. calculate the possible credits until
863 * the sequence numbers start to wrap on 64-bit.
865 * 2. UINT64_MAX is used for Break Notifications.
867 * 2. truncate the possible credits to the maximum
868 * credits we want to grant to the client in total.
870 * 3. remove the range we'll already granted to the client
871 * this makes sure the client consumes the lowest sequence
872 * number, before we can grant additional credits.
874 credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
875 if (credits_possible > 0) {
876 /* remove UINT64_MAX */
877 credits_possible -= 1;
879 credits_possible = MIN(credits_possible, current_max_credits);
880 credits_possible -= xconn->smb2.credits.seq_range;
882 credits_granted = MIN(credits_granted, credits_possible);
884 SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
885 xconn->smb2.credits.granted += credits_granted;
886 xconn->smb2.credits.seq_range += credits_granted;
888 DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
889 "granted %u, current possible/max %u/%u, "
890 "total granted/max/low/range %u/%u/%llu/%u\n",
891 (unsigned int)credits_requested,
892 (unsigned int)credit_charge,
893 (unsigned int)credits_granted,
894 (unsigned int)credits_possible,
895 (unsigned int)current_max_credits,
896 (unsigned int)xconn->smb2.credits.granted,
897 (unsigned int)xconn->smb2.credits.max,
898 (unsigned long long)xconn->smb2.credits.seq_low,
899 (unsigned int)xconn->smb2.credits.seq_range));
902 static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
903 struct smbd_smb2_request *outreq)
905 int count, idx;
906 uint16_t total_credits = 0;
908 count = outreq->out.vector_count;
910 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
911 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
912 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
913 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
915 smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
917 /* To match Windows, count up what we
918 just granted. */
919 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
920 /* Set to zero in all but the last reply. */
921 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
922 SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
923 } else {
924 SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
929 DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
931 if (req->current_idx <= 1) {
932 if (size <= sizeof(req->out._body)) {
933 return data_blob_const(req->out._body, size);
937 return data_blob_talloc(req, NULL, size);
940 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
942 struct smbXsrv_connection *xconn = req->sconn->conn;
943 TALLOC_CTX *mem_ctx;
944 struct iovec *vector;
945 int count;
946 int idx;
948 count = req->in.vector_count;
949 if (count <= ARRAY_SIZE(req->out._vector)) {
950 mem_ctx = req;
951 vector = req->out._vector;
952 } else {
953 vector = talloc_zero_array(req, struct iovec, count);
954 if (vector == NULL) {
955 return NT_STATUS_NO_MEMORY;
957 mem_ctx = vector;
960 vector[0].iov_base = req->out.nbt_hdr;
961 vector[0].iov_len = 4;
962 SIVAL(req->out.nbt_hdr, 0, 0);
964 for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
965 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
966 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
967 uint8_t *outhdr = NULL;
968 uint8_t *outbody = NULL;
969 uint32_t next_command_ofs = 0;
970 struct iovec *current = &vector[idx];
972 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
973 /* we have a next command -
974 * setup for the error case. */
975 next_command_ofs = SMB2_HDR_BODY + 9;
978 if (idx == 1) {
979 outhdr = req->out._hdr;
980 } else {
981 outhdr = talloc_zero_array(mem_ctx, uint8_t,
982 OUTVEC_ALLOC_SIZE);
983 if (outhdr == NULL) {
984 return NT_STATUS_NO_MEMORY;
988 outbody = outhdr + SMB2_HDR_BODY;
991 * SMBD_SMB2_TF_IOV_OFS might be used later
993 current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
994 current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
996 current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
997 current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
999 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1000 current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1002 current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1003 current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1005 /* setup the SMB2 header */
1006 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1007 SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1008 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1009 SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1010 SIVAL(outhdr, SMB2_HDR_STATUS,
1011 NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1012 SSVAL(outhdr, SMB2_HDR_OPCODE,
1013 SVAL(inhdr, SMB2_HDR_OPCODE));
1014 SIVAL(outhdr, SMB2_HDR_FLAGS,
1015 IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1016 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1017 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1018 BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1019 SIVAL(outhdr, SMB2_HDR_PID,
1020 IVAL(inhdr, SMB2_HDR_PID));
1021 SIVAL(outhdr, SMB2_HDR_TID,
1022 IVAL(inhdr, SMB2_HDR_TID));
1023 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1024 BVAL(inhdr, SMB2_HDR_SESSION_ID));
1025 memcpy(outhdr + SMB2_HDR_SIGNATURE,
1026 inhdr + SMB2_HDR_SIGNATURE, 16);
1028 /* setup error body header */
1029 SSVAL(outbody, 0x00, 0x08 + 1);
1030 SSVAL(outbody, 0x02, 0);
1031 SIVAL(outbody, 0x04, 0);
1034 req->out.vector = vector;
1035 req->out.vector_count = count;
1037 /* setup the length of the NBT packet */
1038 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1040 DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
1042 return NT_STATUS_OK;
1045 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
1046 const char *reason,
1047 const char *location)
1049 DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
1050 reason, location));
1051 exit_server_cleanly(reason);
1054 static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1055 struct iovec *outvec,
1056 const struct iovec *srcvec)
1058 const uint8_t *srctf;
1059 size_t srctf_len;
1060 const uint8_t *srchdr;
1061 size_t srchdr_len;
1062 const uint8_t *srcbody;
1063 size_t srcbody_len;
1064 const uint8_t *expected_srcbody;
1065 const uint8_t *srcdyn;
1066 size_t srcdyn_len;
1067 const uint8_t *expected_srcdyn;
1068 uint8_t *dsttf;
1069 uint8_t *dsthdr;
1070 uint8_t *dstbody;
1071 uint8_t *dstdyn;
1073 srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1074 srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1075 srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1076 srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1077 srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1078 srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1079 expected_srcbody = srchdr + SMB2_HDR_BODY;
1080 srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1081 srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1082 expected_srcdyn = srcbody + 8;
1084 if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1085 return false;
1088 if (srchdr_len != SMB2_HDR_BODY) {
1089 return false;
1092 if (srctf_len == SMB2_TF_HDR_SIZE) {
1093 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1094 if (dsttf == NULL) {
1095 return false;
1097 } else {
1098 dsttf = NULL;
1100 outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1101 outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1103 /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1104 * be allocated with size OUTVEC_ALLOC_SIZE. */
1106 dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1107 if (dsthdr == NULL) {
1108 return false;
1110 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1111 outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1114 * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1115 * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1116 * then duplicate this. Else use talloc_memdup().
1119 if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1120 dstbody = dsthdr + SMB2_HDR_BODY;
1121 } else {
1122 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1123 if (dstbody == NULL) {
1124 return false;
1127 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1128 outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1131 * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1132 * pointing to
1133 * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1134 * then duplicate this. Else use talloc_memdup().
1137 if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1138 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1139 } else if (srcdyn == NULL) {
1140 dstdyn = NULL;
1141 } else {
1142 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1143 if (dstdyn == NULL) {
1144 return false;
1147 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1148 outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1150 return true;
1153 static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1155 struct smbd_smb2_request *newreq = NULL;
1156 struct iovec *outvec = NULL;
1157 int count = req->out.vector_count;
1158 int i;
1160 newreq = smbd_smb2_request_allocate(req->xconn);
1161 if (!newreq) {
1162 return NULL;
1165 newreq->sconn = req->sconn;
1166 newreq->xconn = req->xconn;
1167 newreq->session = req->session;
1168 newreq->do_encryption = req->do_encryption;
1169 newreq->do_signing = req->do_signing;
1170 newreq->current_idx = req->current_idx;
1172 outvec = talloc_zero_array(newreq, struct iovec, count);
1173 if (!outvec) {
1174 TALLOC_FREE(newreq);
1175 return NULL;
1177 newreq->out.vector = outvec;
1178 newreq->out.vector_count = count;
1180 /* Setup the outvec's identically to req. */
1181 outvec[0].iov_base = newreq->out.nbt_hdr;
1182 outvec[0].iov_len = 4;
1183 memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1185 /* Setup the vectors identically to the ones in req. */
1186 for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1187 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1188 break;
1192 if (i < count) {
1193 /* Alloc failed. */
1194 TALLOC_FREE(newreq);
1195 return NULL;
1198 smb2_setup_nbt_length(newreq->out.vector,
1199 newreq->out.vector_count);
1201 return newreq;
1204 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1206 struct smbXsrv_connection *xconn = req->xconn;
1207 int first_idx = 1;
1208 struct iovec *firsttf = NULL;
1209 struct iovec *outhdr_v = NULL;
1210 uint8_t *outhdr = NULL;
1211 struct smbd_smb2_request *nreq = NULL;
1212 NTSTATUS status;
1214 /* Create a new smb2 request we'll use
1215 for the interim return. */
1216 nreq = dup_smb2_req(req);
1217 if (!nreq) {
1218 return NT_STATUS_NO_MEMORY;
1221 /* Lose the last X out vectors. They're the
1222 ones we'll be using for the async reply. */
1223 nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1225 smb2_setup_nbt_length(nreq->out.vector,
1226 nreq->out.vector_count);
1228 /* Step back to the previous reply. */
1229 nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1230 firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1231 outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1232 outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1233 /* And end the chain. */
1234 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1236 /* Calculate outgoing credits */
1237 smb2_calculate_credits(req, nreq);
1239 if (DEBUGLEVEL >= 10) {
1240 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1241 (unsigned int)nreq->current_idx );
1242 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1243 (unsigned int)nreq->out.vector_count );
1244 print_req_vectors(nreq);
1248 * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1249 * we need to sign/encrypt here with the last/first key we remembered
1251 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1252 status = smb2_signing_encrypt_pdu(req->first_key,
1253 xconn->protocol,
1254 firsttf,
1255 nreq->out.vector_count - first_idx);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 return status;
1259 } else if (req->last_key.length > 0) {
1260 status = smb2_signing_sign_pdu(req->last_key,
1261 xconn->protocol,
1262 outhdr_v,
1263 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 return status;
1269 nreq->queue_entry.mem_ctx = nreq;
1270 nreq->queue_entry.vector = nreq->out.vector;
1271 nreq->queue_entry.count = nreq->out.vector_count;
1272 DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry, NULL);
1273 xconn->smb2.send_queue_len++;
1275 status = smbd_smb2_flush_send_queue(xconn);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 return status;
1280 return NT_STATUS_OK;
1283 struct smbd_smb2_request_pending_state {
1284 struct smbd_server_connection *sconn;
1285 struct smbd_smb2_send_queue queue_entry;
1286 uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1287 struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1290 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1291 struct tevent_timer *te,
1292 struct timeval current_time,
1293 void *private_data);
1295 NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1296 struct tevent_req *subreq,
1297 uint32_t defer_time)
1299 NTSTATUS status;
1300 struct timeval defer_endtime;
1301 uint8_t *outhdr = NULL;
1302 uint32_t flags;
1304 if (!tevent_req_is_in_progress(subreq)) {
1306 * This is a performance optimization,
1307 * it avoids one tevent_loop iteration,
1308 * which means we avoid one
1309 * talloc_stackframe_pool/talloc_free pair.
1311 tevent_req_notify_callback(subreq);
1312 return NT_STATUS_OK;
1315 req->subreq = subreq;
1316 subreq = NULL;
1318 if (req->async_te) {
1319 /* We're already async. */
1320 return NT_STATUS_OK;
1323 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1324 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1325 if (flags & SMB2_HDR_FLAG_ASYNC) {
1326 /* We're already async. */
1327 return NT_STATUS_OK;
1330 if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
1332 * We're trying to go async in a compound
1333 * request chain.
1334 * This is only allowed for opens that
1335 * cause an oplock break, otherwise it
1336 * is not allowed. See [MS-SMB2].pdf
1337 * note <194> on Section 3.3.5.2.7.
1339 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1341 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
1343 * Cancel the outstanding request.
1345 bool ok = tevent_req_cancel(req->subreq);
1346 if (ok) {
1347 return NT_STATUS_OK;
1349 TALLOC_FREE(req->subreq);
1350 return smbd_smb2_request_error(req,
1351 NT_STATUS_INTERNAL_ERROR);
1355 if (DEBUGLEVEL >= 10) {
1356 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
1357 (unsigned int)req->current_idx );
1358 print_req_vectors(req);
1361 if (req->current_idx > 1) {
1363 * We're going async in a compound
1364 * chain after the first request has
1365 * already been processed. Send an
1366 * interim response containing the
1367 * set of replies already generated.
1369 int idx = req->current_idx;
1371 status = smb2_send_async_interim_response(req);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 return status;
1375 if (req->first_key.length > 0) {
1376 data_blob_clear_free(&req->first_key);
1379 req->current_idx = 1;
1382 * Re-arrange the in.vectors to remove what
1383 * we just sent.
1385 memmove(&req->in.vector[1],
1386 &req->in.vector[idx],
1387 sizeof(req->in.vector[0])*(req->in.vector_count - idx));
1388 req->in.vector_count = 1 + (req->in.vector_count - idx);
1390 /* Re-arrange the out.vectors to match. */
1391 memmove(&req->out.vector[1],
1392 &req->out.vector[idx],
1393 sizeof(req->out.vector[0])*(req->out.vector_count - idx));
1394 req->out.vector_count = 1 + (req->out.vector_count - idx);
1396 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
1398 * We only have one remaining request as
1399 * we've processed everything else.
1400 * This is no longer a compound request.
1402 req->compound_related = false;
1403 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1404 flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
1405 SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
1408 if (req->last_key.length > 0) {
1409 data_blob_clear_free(&req->last_key);
1412 defer_endtime = timeval_current_ofs_usec(defer_time);
1413 req->async_te = tevent_add_timer(req->sconn->ev_ctx,
1414 req, defer_endtime,
1415 smbd_smb2_request_pending_timer,
1416 req);
1417 if (req->async_te == NULL) {
1418 return NT_STATUS_NO_MEMORY;
1421 return NT_STATUS_OK;
1424 static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1425 struct tevent_timer *te,
1426 struct timeval current_time,
1427 void *private_data)
1429 struct smbd_smb2_request *req =
1430 talloc_get_type_abort(private_data,
1431 struct smbd_smb2_request);
1432 struct smbd_server_connection *sconn = req->sconn;
1433 struct smbXsrv_connection *xconn = sconn->conn;
1434 struct smbd_smb2_request_pending_state *state = NULL;
1435 uint8_t *outhdr = NULL;
1436 const uint8_t *inhdr = NULL;
1437 uint8_t *tf = NULL;
1438 size_t tf_len = 0;
1439 uint8_t *hdr = NULL;
1440 uint8_t *body = NULL;
1441 uint8_t *dyn = NULL;
1442 uint32_t flags = 0;
1443 uint64_t session_id = 0;
1444 uint64_t message_id = 0;
1445 uint64_t nonce_high = 0;
1446 uint64_t nonce_low = 0;
1447 uint64_t async_id = 0;
1448 NTSTATUS status;
1450 TALLOC_FREE(req->async_te);
1452 /* Ensure our final reply matches the interim one. */
1453 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1454 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
1455 flags = IVAL(outhdr, SMB2_HDR_FLAGS);
1456 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1457 session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1459 async_id = message_id; /* keep it simple for now... */
1461 SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1462 SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
1464 DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
1465 "going async\n",
1466 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1467 (unsigned long long)async_id ));
1470 * What we send is identical to a smbd_smb2_request_error
1471 * packet with an error status of STATUS_PENDING. Make use
1472 * of this fact sometime when refactoring. JRA.
1475 state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
1476 if (state == NULL) {
1477 smbd_server_connection_terminate(req->sconn,
1478 nt_errstr(NT_STATUS_NO_MEMORY));
1479 return;
1481 state->sconn = req->sconn;
1483 tf = state->buf + NBT_HDR_SIZE;
1484 tf_len = SMB2_TF_HDR_SIZE;
1486 hdr = tf + SMB2_TF_HDR_SIZE;
1487 body = hdr + SMB2_HDR_BODY;
1488 dyn = body + 8;
1490 if (req->do_encryption) {
1491 struct smbXsrv_session *x = req->session;
1493 nonce_high = x->nonce_high;
1494 nonce_low = x->nonce_low;
1496 x->nonce_low += 1;
1497 if (x->nonce_low == 0) {
1498 x->nonce_low += 1;
1499 x->nonce_high += 1;
1503 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
1504 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
1505 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
1506 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
1508 SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1509 SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1510 SSVAL(hdr, SMB2_HDR_EPOCH, 0);
1511 SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
1512 SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
1514 SIVAL(hdr, SMB2_HDR_FLAGS, flags);
1515 SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
1516 SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
1517 SBVAL(hdr, SMB2_HDR_PID, async_id);
1518 SBVAL(hdr, SMB2_HDR_SESSION_ID,
1519 BVAL(outhdr, SMB2_HDR_SESSION_ID));
1520 memcpy(hdr+SMB2_HDR_SIGNATURE,
1521 outhdr+SMB2_HDR_SIGNATURE, 16);
1523 SSVAL(body, 0x00, 0x08 + 1);
1525 SCVAL(body, 0x02, 0);
1526 SCVAL(body, 0x03, 0);
1527 SIVAL(body, 0x04, 0);
1528 /* Match W2K8R2... */
1529 SCVAL(dyn, 0x00, 0x21);
1531 state->vector[0].iov_base = (void *)state->buf;
1532 state->vector[0].iov_len = NBT_HDR_SIZE;
1534 if (req->do_encryption) {
1535 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
1536 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
1537 } else {
1538 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1539 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1542 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
1543 state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1545 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
1546 state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1548 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
1549 state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
1551 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
1553 /* Ensure we correctly go through crediting. Grant
1554 the credits now, and zero credits on the final
1555 response. */
1556 smb2_set_operation_credit(req->sconn,
1557 SMBD_SMB2_IN_HDR_IOV(req),
1558 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
1560 SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
1562 if (DEBUGLVL(10)) {
1563 int i;
1565 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
1566 dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
1567 (unsigned int)i,
1568 (unsigned int)ARRAY_SIZE(state->vector),
1569 (unsigned int)state->vector[i].iov_len);
1573 if (req->do_encryption) {
1574 struct smbXsrv_session *x = req->session;
1575 DATA_BLOB encryption_key = x->global->encryption_key;
1577 status = smb2_signing_encrypt_pdu(encryption_key,
1578 xconn->protocol,
1579 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
1580 SMBD_SMB2_NUM_IOV_PER_REQ);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 smbd_server_connection_terminate(req->sconn,
1583 nt_errstr(status));
1584 return;
1586 } else if (req->do_signing) {
1587 struct smbXsrv_session *x = req->session;
1588 DATA_BLOB signing_key = x->global->channels[0].signing_key;
1590 status = smb2_signing_sign_pdu(signing_key,
1591 xconn->protocol,
1592 &state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
1593 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 smbd_server_connection_terminate(req->sconn,
1596 nt_errstr(status));
1597 return;
1601 state->queue_entry.mem_ctx = state;
1602 state->queue_entry.vector = state->vector;
1603 state->queue_entry.count = ARRAY_SIZE(state->vector);
1604 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
1605 xconn->smb2.send_queue_len++;
1607 status = smbd_smb2_flush_send_queue(xconn);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 smbd_server_connection_terminate(sconn,
1610 nt_errstr(status));
1611 return;
1615 static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
1617 struct smbd_server_connection *sconn = req->sconn;
1618 struct smbXsrv_connection *xconn = sconn->conn;
1619 struct smbd_smb2_request *cur;
1620 const uint8_t *inhdr;
1621 uint32_t flags;
1622 uint64_t search_message_id;
1623 uint64_t search_async_id;
1624 uint64_t found_id;
1626 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1628 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1629 search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1630 search_async_id = BVAL(inhdr, SMB2_HDR_PID);
1633 * we don't need the request anymore
1634 * cancel requests never have a response
1636 DLIST_REMOVE(xconn->smb2.requests, req);
1637 TALLOC_FREE(req);
1639 for (cur = xconn->smb2.requests; cur; cur = cur->next) {
1640 const uint8_t *outhdr;
1641 uint64_t message_id;
1642 uint64_t async_id;
1644 if (cur->compound_related) {
1646 * Never cancel anything in a compound request.
1647 * Way too hard to deal with the result.
1649 continue;
1652 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
1654 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
1655 async_id = BVAL(outhdr, SMB2_HDR_PID);
1657 if (flags & SMB2_HDR_FLAG_ASYNC) {
1658 if (search_async_id == async_id) {
1659 found_id = async_id;
1660 break;
1662 } else {
1663 if (search_message_id == message_id) {
1664 found_id = message_id;
1665 break;
1670 if (cur && cur->subreq) {
1671 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
1672 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
1673 "cancel opcode[%s] mid %llu\n",
1674 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
1675 (unsigned long long)found_id ));
1676 tevent_req_cancel(cur->subreq);
1679 return NT_STATUS_OK;
1682 /*************************************************************
1683 Ensure an incoming tid is a valid one for us to access.
1684 Change to the associated uid credentials and chdir to the
1685 valid tid directory.
1686 *************************************************************/
1688 static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
1690 const uint8_t *inhdr;
1691 uint32_t in_flags;
1692 uint32_t in_tid;
1693 struct smbXsrv_tcon *tcon;
1694 NTSTATUS status;
1695 NTTIME now = timeval_to_nttime(&req->request_time);
1697 req->tcon = NULL;
1699 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1701 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1702 in_tid = IVAL(inhdr, SMB2_HDR_TID);
1704 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1705 in_tid = req->last_tid;
1708 req->last_tid = 0;
1710 status = smb2srv_tcon_lookup(req->session,
1711 in_tid, now, &tcon);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 return status;
1716 if (!change_to_user(tcon->compat, req->session->compat->vuid)) {
1717 return NT_STATUS_ACCESS_DENIED;
1720 /* should we pass FLAG_CASELESS_PATHNAMES here? */
1721 if (!set_current_service(tcon->compat, 0, true)) {
1722 return NT_STATUS_ACCESS_DENIED;
1725 req->tcon = tcon;
1726 req->last_tid = in_tid;
1728 return NT_STATUS_OK;
1731 /*************************************************************
1732 Ensure an incoming session_id is a valid one for us to access.
1733 *************************************************************/
1735 static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
1737 const uint8_t *inhdr;
1738 uint32_t in_flags;
1739 uint16_t in_opcode;
1740 uint64_t in_session_id;
1741 struct smbXsrv_session *session = NULL;
1742 struct auth_session_info *session_info;
1743 NTSTATUS status;
1744 NTTIME now = timeval_to_nttime(&req->request_time);
1746 req->session = NULL;
1747 req->tcon = NULL;
1749 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1751 in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1752 in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1753 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
1755 if (in_flags & SMB2_HDR_FLAG_CHAINED) {
1756 in_session_id = req->last_session_id;
1759 req->last_session_id = 0;
1761 /* lookup an existing session */
1762 status = smb2srv_session_lookup(req->sconn->conn,
1763 in_session_id, now,
1764 &session);
1765 if (session) {
1766 req->session = session;
1767 req->last_session_id = in_session_id;
1769 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1770 switch (in_opcode) {
1771 case SMB2_OP_SESSSETUP:
1772 status = NT_STATUS_OK;
1773 break;
1774 default:
1775 break;
1778 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1779 switch (in_opcode) {
1780 case SMB2_OP_TCON:
1781 case SMB2_OP_CREATE:
1782 case SMB2_OP_GETINFO:
1783 case SMB2_OP_SETINFO:
1784 return NT_STATUS_INVALID_HANDLE;
1785 default:
1787 * Notice the check for
1788 * (session_info == NULL)
1789 * below.
1791 status = NT_STATUS_OK;
1792 break;
1795 if (!NT_STATUS_IS_OK(status)) {
1796 return status;
1799 session_info = session->global->auth_session_info;
1800 if (session_info == NULL) {
1801 return NT_STATUS_INVALID_HANDLE;
1804 if (in_session_id != req->sconn->conn->last_session_id) {
1805 req->sconn->conn->last_session_id = in_session_id;
1806 set_current_user_info(session_info->unix_info->sanitized_username,
1807 session_info->unix_info->unix_name,
1808 session_info->info->domain_name);
1811 return NT_STATUS_OK;
1814 NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
1815 uint32_t data_length)
1817 struct smbXsrv_connection *xconn = req->sconn->conn;
1818 uint16_t needed_charge;
1819 uint16_t credit_charge = 1;
1820 const uint8_t *inhdr;
1822 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1824 if (xconn->smb2.credits.multicredit) {
1825 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
1826 credit_charge = MAX(credit_charge, 1);
1829 needed_charge = (data_length - 1)/ 65536 + 1;
1831 DEBUG(10, ("mid %llu, CreditCharge: %d, NeededCharge: %d\n",
1832 (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
1833 credit_charge, needed_charge));
1835 if (needed_charge > credit_charge) {
1836 DEBUG(2, ("CreditCharge too low, given %d, needed %d\n",
1837 credit_charge, needed_charge));
1838 return NT_STATUS_INVALID_PARAMETER;
1841 return NT_STATUS_OK;
1844 NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
1845 size_t expected_body_size)
1847 struct iovec *inhdr_v;
1848 const uint8_t *inhdr;
1849 uint16_t opcode;
1850 const uint8_t *inbody;
1851 size_t body_size;
1852 size_t min_dyn_size = expected_body_size & 0x00000001;
1853 int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
1856 * The following should be checked already.
1858 if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
1859 return NT_STATUS_INTERNAL_ERROR;
1861 if (req->current_idx > max_idx) {
1862 return NT_STATUS_INTERNAL_ERROR;
1865 inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
1866 if (inhdr_v->iov_len != SMB2_HDR_BODY) {
1867 return NT_STATUS_INTERNAL_ERROR;
1869 if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
1870 return NT_STATUS_INTERNAL_ERROR;
1873 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1874 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1876 switch (opcode) {
1877 case SMB2_OP_IOCTL:
1878 case SMB2_OP_GETINFO:
1879 min_dyn_size = 0;
1880 break;
1881 case SMB2_OP_WRITE:
1882 if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
1883 if (req->smb1req->unread_bytes < min_dyn_size) {
1884 return NT_STATUS_INVALID_PARAMETER;
1887 min_dyn_size = 0;
1889 break;
1893 * Now check the expected body size,
1894 * where the last byte might be in the
1895 * dynamic section..
1897 if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
1898 return NT_STATUS_INVALID_PARAMETER;
1900 if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
1901 return NT_STATUS_INVALID_PARAMETER;
1904 inbody = SMBD_SMB2_IN_BODY_PTR(req);
1906 body_size = SVAL(inbody, 0x00);
1907 if (body_size != expected_body_size) {
1908 return NT_STATUS_INVALID_PARAMETER;
1911 return NT_STATUS_OK;
1914 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
1916 struct smbXsrv_connection *xconn = req->sconn->conn;
1917 const struct smbd_smb2_dispatch_table *call = NULL;
1918 const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
1919 const uint8_t *inhdr;
1920 uint16_t opcode;
1921 uint32_t flags;
1922 uint64_t mid;
1923 NTSTATUS status;
1924 NTSTATUS session_status;
1925 uint32_t allowed_flags;
1926 NTSTATUS return_value;
1927 struct smbXsrv_session *x = NULL;
1928 bool signing_required = false;
1929 bool encryption_required = false;
1931 inhdr = SMBD_SMB2_IN_HDR_PTR(req);
1933 /* TODO: verify more things */
1935 flags = IVAL(inhdr, SMB2_HDR_FLAGS);
1936 opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
1937 mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
1938 DEBUG(10,("smbd_smb2_request_dispatch: opcode[%s] mid = %llu\n",
1939 smb2_opcode_name(opcode),
1940 (unsigned long long)mid));
1942 if (xconn->protocol >= PROTOCOL_SMB2_02) {
1944 * once the protocol is negotiated
1945 * SMB2_OP_NEGPROT is not allowed anymore
1947 if (opcode == SMB2_OP_NEGPROT) {
1948 /* drop the connection */
1949 return NT_STATUS_INVALID_PARAMETER;
1951 } else {
1953 * if the protocol is not negotiated yet
1954 * only SMB2_OP_NEGPROT is allowed.
1956 if (opcode != SMB2_OP_NEGPROT) {
1957 /* drop the connection */
1958 return NT_STATUS_INVALID_PARAMETER;
1963 * Check if the client provided a valid session id,
1964 * if so smbd_smb2_request_check_session() calls
1965 * set_current_user_info().
1967 * As some command don't require a valid session id
1968 * we defer the check of the session_status
1970 session_status = smbd_smb2_request_check_session(req);
1971 x = req->session;
1972 if (x != NULL) {
1973 signing_required = x->global->signing_required;
1974 encryption_required = x->global->encryption_required;
1976 if (opcode == SMB2_OP_SESSSETUP &&
1977 x->global->channels[0].signing_key.length) {
1978 signing_required = true;
1982 req->do_signing = false;
1983 req->do_encryption = false;
1984 if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
1985 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
1986 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
1988 if (x != NULL && x->global->session_wire_id != tf_session_id) {
1989 DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
1990 "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
1991 (unsigned long long)x->global->session_wire_id,
1992 (unsigned long long)tf_session_id));
1994 * TODO: windows allows this...
1995 * should we drop the connection?
1997 * For now we just return ACCESS_DENIED
1998 * (Windows clients never trigger this)
1999 * and wait for an update of [MS-SMB2].
2001 return smbd_smb2_request_error(req,
2002 NT_STATUS_ACCESS_DENIED);
2005 req->do_encryption = true;
2008 if (encryption_required && !req->do_encryption) {
2009 return smbd_smb2_request_error(req,
2010 NT_STATUS_ACCESS_DENIED);
2013 call = smbd_smb2_call(opcode);
2014 if (call == NULL) {
2015 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2018 allowed_flags = SMB2_HDR_FLAG_CHAINED |
2019 SMB2_HDR_FLAG_SIGNED |
2020 SMB2_HDR_FLAG_DFS;
2021 if (opcode == SMB2_OP_CANCEL) {
2022 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
2024 if ((flags & ~allowed_flags) != 0) {
2025 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2028 if (flags & SMB2_HDR_FLAG_CHAINED) {
2030 * This check is mostly for giving the correct error code
2031 * for compounded requests.
2033 if (!NT_STATUS_IS_OK(session_status)) {
2034 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2036 } else {
2037 req->compat_chain_fsp = NULL;
2040 if (req->do_encryption) {
2041 signing_required = false;
2042 } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
2043 DATA_BLOB signing_key;
2045 if (x == NULL) {
2047 * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
2048 * If the SMB2 header of the SMB2 NEGOTIATE
2049 * request has the SMB2_FLAGS_SIGNED bit set in the
2050 * Flags field, the server MUST fail the request
2051 * with STATUS_INVALID_PARAMETER.
2053 * Microsoft test tool checks this.
2056 if ((opcode == SMB2_OP_NEGPROT) &&
2057 (flags & SMB2_HDR_FLAG_SIGNED)) {
2058 status = NT_STATUS_INVALID_PARAMETER;
2059 } else {
2060 status = NT_STATUS_USER_SESSION_DELETED;
2062 return smbd_smb2_request_error(req, status);
2065 signing_key = x->global->channels[0].signing_key;
2068 * If we have a signing key, we should
2069 * sign the response
2071 if (signing_key.length > 0) {
2072 req->do_signing = true;
2075 status = smb2_signing_check_pdu(signing_key,
2076 xconn->protocol,
2077 SMBD_SMB2_IN_HDR_IOV(req),
2078 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2079 if (!NT_STATUS_IS_OK(status)) {
2080 return smbd_smb2_request_error(req, status);
2084 * Now that we know the request was correctly signed
2085 * we have to sign the response too.
2087 req->do_signing = true;
2089 if (!NT_STATUS_IS_OK(session_status)) {
2090 return smbd_smb2_request_error(req, session_status);
2092 } else if (opcode == SMB2_OP_CANCEL) {
2093 /* Cancel requests are allowed to skip the signing */
2094 } else if (signing_required) {
2096 * If signing is required we try to sign
2097 * a possible error response
2099 req->do_signing = true;
2100 return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
2103 if (flags & SMB2_HDR_FLAG_CHAINED) {
2104 req->compound_related = true;
2107 if (call->need_session) {
2108 if (!NT_STATUS_IS_OK(session_status)) {
2109 return smbd_smb2_request_error(req, session_status);
2113 if (call->need_tcon) {
2114 SMB_ASSERT(call->need_session);
2117 * This call needs to be run as user.
2119 * smbd_smb2_request_check_tcon()
2120 * calls change_to_user() on success.
2122 status = smbd_smb2_request_check_tcon(req);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 return smbd_smb2_request_error(req, status);
2126 if (req->tcon->global->encryption_required) {
2127 encryption_required = true;
2129 if (encryption_required && !req->do_encryption) {
2130 return smbd_smb2_request_error(req,
2131 NT_STATUS_ACCESS_DENIED);
2135 if (call->fileid_ofs != 0) {
2136 size_t needed = call->fileid_ofs + 16;
2137 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
2138 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
2139 uint64_t file_id_persistent;
2140 uint64_t file_id_volatile;
2141 struct files_struct *fsp;
2143 SMB_ASSERT(call->need_tcon);
2145 if (needed > body_size) {
2146 return smbd_smb2_request_error(req,
2147 NT_STATUS_INVALID_PARAMETER);
2150 file_id_persistent = BVAL(body, call->fileid_ofs + 0);
2151 file_id_volatile = BVAL(body, call->fileid_ofs + 8);
2153 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
2154 if (fsp == NULL) {
2155 if (!call->allow_invalid_fileid) {
2156 return smbd_smb2_request_error(req,
2157 NT_STATUS_FILE_CLOSED);
2160 if (file_id_persistent != UINT64_MAX) {
2161 return smbd_smb2_request_error(req,
2162 NT_STATUS_FILE_CLOSED);
2164 if (file_id_volatile != UINT64_MAX) {
2165 return smbd_smb2_request_error(req,
2166 NT_STATUS_FILE_CLOSED);
2171 if (call->as_root) {
2172 SMB_ASSERT(call->fileid_ofs == 0);
2173 /* This call needs to be run as root */
2174 change_to_root_user();
2175 } else {
2176 SMB_ASSERT(call->need_tcon);
2179 switch (opcode) {
2180 case SMB2_OP_NEGPROT:
2182 START_PROFILE(smb2_negprot);
2183 return_value = smbd_smb2_request_process_negprot(req);
2184 END_PROFILE(smb2_negprot);
2186 break;
2188 case SMB2_OP_SESSSETUP:
2190 START_PROFILE(smb2_sesssetup);
2191 return_value = smbd_smb2_request_process_sesssetup(req);
2192 END_PROFILE(smb2_sesssetup);
2194 break;
2196 case SMB2_OP_LOGOFF:
2198 START_PROFILE(smb2_logoff);
2199 return_value = smbd_smb2_request_process_logoff(req);
2200 END_PROFILE(smb2_logoff);
2202 break;
2204 case SMB2_OP_TCON:
2206 START_PROFILE(smb2_tcon);
2207 return_value = smbd_smb2_request_process_tcon(req);
2208 END_PROFILE(smb2_tcon);
2210 break;
2212 case SMB2_OP_TDIS:
2214 START_PROFILE(smb2_tdis);
2215 return_value = smbd_smb2_request_process_tdis(req);
2216 END_PROFILE(smb2_tdis);
2218 break;
2220 case SMB2_OP_CREATE:
2222 START_PROFILE(smb2_create);
2223 return_value = smbd_smb2_request_process_create(req);
2224 END_PROFILE(smb2_create);
2226 break;
2228 case SMB2_OP_CLOSE:
2230 START_PROFILE(smb2_close);
2231 return_value = smbd_smb2_request_process_close(req);
2232 END_PROFILE(smb2_close);
2234 break;
2236 case SMB2_OP_FLUSH:
2238 START_PROFILE(smb2_flush);
2239 return_value = smbd_smb2_request_process_flush(req);
2240 END_PROFILE(smb2_flush);
2242 break;
2244 case SMB2_OP_READ:
2246 START_PROFILE(smb2_read);
2247 return_value = smbd_smb2_request_process_read(req);
2248 END_PROFILE(smb2_read);
2250 break;
2252 case SMB2_OP_WRITE:
2254 START_PROFILE(smb2_write);
2255 return_value = smbd_smb2_request_process_write(req);
2256 END_PROFILE(smb2_write);
2258 break;
2260 case SMB2_OP_LOCK:
2262 START_PROFILE(smb2_lock);
2263 return_value = smbd_smb2_request_process_lock(req);
2264 END_PROFILE(smb2_lock);
2266 break;
2268 case SMB2_OP_IOCTL:
2270 START_PROFILE(smb2_ioctl);
2271 return_value = smbd_smb2_request_process_ioctl(req);
2272 END_PROFILE(smb2_ioctl);
2274 break;
2276 case SMB2_OP_CANCEL:
2278 START_PROFILE(smb2_cancel);
2279 return_value = smbd_smb2_request_process_cancel(req);
2280 END_PROFILE(smb2_cancel);
2282 break;
2284 case SMB2_OP_KEEPALIVE:
2286 START_PROFILE(smb2_keepalive);
2287 return_value = smbd_smb2_request_process_keepalive(req);
2288 END_PROFILE(smb2_keepalive);
2290 break;
2292 case SMB2_OP_FIND:
2294 START_PROFILE(smb2_find);
2295 return_value = smbd_smb2_request_process_find(req);
2296 END_PROFILE(smb2_find);
2298 break;
2300 case SMB2_OP_NOTIFY:
2302 START_PROFILE(smb2_notify);
2303 return_value = smbd_smb2_request_process_notify(req);
2304 END_PROFILE(smb2_notify);
2306 break;
2308 case SMB2_OP_GETINFO:
2310 START_PROFILE(smb2_getinfo);
2311 return_value = smbd_smb2_request_process_getinfo(req);
2312 END_PROFILE(smb2_getinfo);
2314 break;
2316 case SMB2_OP_SETINFO:
2318 START_PROFILE(smb2_setinfo);
2319 return_value = smbd_smb2_request_process_setinfo(req);
2320 END_PROFILE(smb2_setinfo);
2322 break;
2324 case SMB2_OP_BREAK:
2326 START_PROFILE(smb2_break);
2327 return_value = smbd_smb2_request_process_break(req);
2328 END_PROFILE(smb2_break);
2330 break;
2332 default:
2333 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
2334 break;
2336 return return_value;
2339 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
2341 struct smbXsrv_connection *xconn = req->xconn;
2342 int first_idx = 1;
2343 struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
2344 struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
2345 struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
2346 NTSTATUS status;
2348 req->subreq = NULL;
2349 TALLOC_FREE(req->async_te);
2351 if (req->do_encryption &&
2352 (firsttf->iov_len == 0) &&
2353 (req->first_key.length == 0) &&
2354 (req->session != NULL) &&
2355 (req->session->global->encryption_key.length != 0))
2357 DATA_BLOB encryption_key = req->session->global->encryption_key;
2358 uint8_t *tf;
2359 uint64_t session_id = req->session->global->session_wire_id;
2360 struct smbXsrv_session *x = req->session;
2361 uint64_t nonce_high;
2362 uint64_t nonce_low;
2364 nonce_high = x->nonce_high;
2365 nonce_low = x->nonce_low;
2367 x->nonce_low += 1;
2368 if (x->nonce_low == 0) {
2369 x->nonce_low += 1;
2370 x->nonce_high += 1;
2374 * We need to place the SMB2_TRANSFORM header before the
2375 * first SMB2 header
2379 * we need to remember the encryption key
2380 * and defer the signing/encryption until
2381 * we are sure that we do not change
2382 * the header again.
2384 req->first_key = data_blob_dup_talloc(req, encryption_key);
2385 if (req->first_key.data == NULL) {
2386 return NT_STATUS_NO_MEMORY;
2389 tf = talloc_zero_array(req, uint8_t,
2390 SMB2_TF_HDR_SIZE);
2391 if (tf == NULL) {
2392 return NT_STATUS_NO_MEMORY;
2395 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2396 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2397 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2398 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2400 firsttf->iov_base = (void *)tf;
2401 firsttf->iov_len = SMB2_TF_HDR_SIZE;
2404 if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
2405 (req->last_key.length > 0) &&
2406 (firsttf->iov_len == 0))
2408 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
2409 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
2412 * As we are sure the header of the last request in the
2413 * compound chain will not change, we can to sign here
2414 * with the last signing key we remembered.
2416 status = smb2_signing_sign_pdu(req->last_key,
2417 xconn->protocol,
2418 lasthdr,
2419 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 return status;
2424 if (req->last_key.length > 0) {
2425 data_blob_clear_free(&req->last_key);
2428 req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
2430 if (req->current_idx < req->out.vector_count) {
2432 * We must process the remaining compound
2433 * SMB2 requests before any new incoming SMB2
2434 * requests. This is because incoming SMB2
2435 * requests may include a cancel for a
2436 * compound request we haven't processed
2437 * yet.
2439 struct tevent_immediate *im = tevent_create_immediate(req);
2440 if (!im) {
2441 return NT_STATUS_NO_MEMORY;
2444 if (req->do_signing && firsttf->iov_len == 0) {
2445 struct smbXsrv_session *x = req->session;
2446 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2449 * we need to remember the signing key
2450 * and defer the signing until
2451 * we are sure that we do not change
2452 * the header again.
2454 req->last_key = data_blob_dup_talloc(req, signing_key);
2455 if (req->last_key.data == NULL) {
2456 return NT_STATUS_NO_MEMORY;
2460 tevent_schedule_immediate(im,
2461 req->sconn->ev_ctx,
2462 smbd_smb2_request_dispatch_immediate,
2463 req);
2464 return NT_STATUS_OK;
2467 if (req->compound_related) {
2468 req->compound_related = false;
2471 smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
2473 /* Set credit for these operations (zero credits if this
2474 is a final reply for an async operation). */
2475 smb2_calculate_credits(req, req);
2478 * now check if we need to sign the current response
2480 if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
2481 status = smb2_signing_encrypt_pdu(req->first_key,
2482 xconn->protocol,
2483 firsttf,
2484 req->out.vector_count - first_idx);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 return status;
2488 } else if (req->do_signing) {
2489 struct smbXsrv_session *x = req->session;
2490 DATA_BLOB signing_key = x->global->channels[0].signing_key;
2492 status = smb2_signing_sign_pdu(signing_key,
2493 xconn->protocol,
2494 outhdr,
2495 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 return status;
2500 if (req->first_key.length > 0) {
2501 data_blob_clear_free(&req->first_key);
2504 /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
2505 if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
2506 outdyn->iov_base == NULL && outdyn->iov_len != 0) {
2507 /* Dynamic part is NULL. Chop it off,
2508 We're going to send it via sendfile. */
2509 req->out.vector_count -= 1;
2513 * We're done with this request -
2514 * move it off the "being processed" queue.
2516 DLIST_REMOVE(xconn->smb2.requests, req);
2518 req->queue_entry.mem_ctx = req;
2519 req->queue_entry.vector = req->out.vector;
2520 req->queue_entry.count = req->out.vector_count;
2521 DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry, NULL);
2522 xconn->smb2.send_queue_len++;
2524 status = smbd_smb2_flush_send_queue(xconn);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 return status;
2529 return NT_STATUS_OK;
2532 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
2534 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
2535 struct tevent_immediate *im,
2536 void *private_data)
2538 struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
2539 struct smbd_smb2_request);
2540 struct smbd_server_connection *sconn = req->sconn;
2541 NTSTATUS status;
2543 TALLOC_FREE(im);
2545 if (DEBUGLEVEL >= 10) {
2546 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
2547 req->current_idx, req->in.vector_count));
2548 print_req_vectors(req);
2551 status = smbd_smb2_request_dispatch(req);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 smbd_server_connection_terminate(sconn, nt_errstr(status));
2554 return;
2557 status = smbd_smb2_request_next_incoming(sconn);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 smbd_server_connection_terminate(sconn, nt_errstr(status));
2560 return;
2564 NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
2565 NTSTATUS status,
2566 DATA_BLOB body, DATA_BLOB *dyn,
2567 const char *location)
2569 uint8_t *outhdr;
2570 struct iovec *outbody_v;
2571 struct iovec *outdyn_v;
2572 uint32_t next_command_ofs;
2574 DEBUG(10,("smbd_smb2_request_done_ex: "
2575 "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
2576 req->current_idx, nt_errstr(status), (unsigned int)body.length,
2577 dyn ? "yes": "no",
2578 (unsigned int)(dyn ? dyn->length : 0),
2579 location));
2581 if (body.length < 2) {
2582 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2585 if ((body.length % 2) != 0) {
2586 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
2589 outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2590 outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
2591 outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
2593 next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
2594 SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
2596 outbody_v->iov_base = (void *)body.data;
2597 outbody_v->iov_len = body.length;
2599 if (dyn) {
2600 outdyn_v->iov_base = (void *)dyn->data;
2601 outdyn_v->iov_len = dyn->length;
2602 } else {
2603 outdyn_v->iov_base = NULL;
2604 outdyn_v->iov_len = 0;
2607 /* see if we need to recalculate the offset to the next response */
2608 if (next_command_ofs > 0) {
2609 next_command_ofs = SMB2_HDR_BODY;
2610 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
2611 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
2614 if ((next_command_ofs % 8) != 0) {
2615 size_t pad_size = 8 - (next_command_ofs % 8);
2616 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
2618 * if the dyn buffer is empty
2619 * we can use it to add padding
2621 uint8_t *pad;
2623 pad = talloc_zero_array(req,
2624 uint8_t, pad_size);
2625 if (pad == NULL) {
2626 return smbd_smb2_request_error(req,
2627 NT_STATUS_NO_MEMORY);
2630 outdyn_v->iov_base = (void *)pad;
2631 outdyn_v->iov_len = pad_size;
2632 } else {
2634 * For now we copy the dynamic buffer
2635 * and add the padding to the new buffer
2637 size_t old_size;
2638 uint8_t *old_dyn;
2639 size_t new_size;
2640 uint8_t *new_dyn;
2642 old_size = SMBD_SMB2_OUT_DYN_LEN(req);
2643 old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
2645 new_size = old_size + pad_size;
2646 new_dyn = talloc_zero_array(req,
2647 uint8_t, new_size);
2648 if (new_dyn == NULL) {
2649 return smbd_smb2_request_error(req,
2650 NT_STATUS_NO_MEMORY);
2653 memcpy(new_dyn, old_dyn, old_size);
2654 memset(new_dyn + old_size, 0, pad_size);
2656 outdyn_v->iov_base = (void *)new_dyn;
2657 outdyn_v->iov_len = new_size;
2659 next_command_ofs += pad_size;
2662 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
2664 return smbd_smb2_request_reply(req);
2667 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
2668 NTSTATUS status,
2669 DATA_BLOB *info,
2670 const char *location)
2672 struct smbXsrv_connection *xconn = req->sconn->conn;
2673 DATA_BLOB body;
2674 DATA_BLOB _dyn;
2675 uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2676 size_t unread_bytes = smbd_smb2_unread_bytes(req);
2678 DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
2679 req->current_idx, nt_errstr(status), info ? " +info" : "",
2680 location));
2682 if (unread_bytes) {
2683 /* Recvfile error. Drain incoming socket. */
2684 size_t ret;
2686 errno = 0;
2687 ret = drain_socket(xconn->transport.sock, unread_bytes);
2688 if (ret != unread_bytes) {
2689 NTSTATUS error;
2691 if (errno == 0) {
2692 error = NT_STATUS_IO_DEVICE_ERROR;
2693 } else {
2694 error = map_nt_error_from_unix_common(errno);
2697 DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
2698 "ret[%u] errno[%d] => %s\n",
2699 (unsigned)unread_bytes,
2700 (unsigned)ret, errno, nt_errstr(error)));
2701 return error;
2705 body.data = outhdr + SMB2_HDR_BODY;
2706 body.length = 8;
2707 SSVAL(body.data, 0, 9);
2709 if (info) {
2710 SIVAL(body.data, 0x04, info->length);
2711 } else {
2712 /* Allocated size of req->out.vector[i].iov_base
2713 * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
2714 * 1 byte without having to do an alloc.
2716 info = &_dyn;
2717 info->data = ((uint8_t *)outhdr) +
2718 OUTVEC_ALLOC_SIZE - 1;
2719 info->length = 1;
2720 SCVAL(info->data, 0, 0);
2724 * Note: Even if there is an error, continue to process the request.
2725 * per MS-SMB2.
2728 return smbd_smb2_request_done_ex(req, status, body, info, __location__);
2732 struct smbd_smb2_send_break_state {
2733 struct smbd_server_connection *sconn;
2734 struct smbd_smb2_send_queue queue_entry;
2735 uint8_t nbt_hdr[NBT_HDR_SIZE];
2736 uint8_t tf[SMB2_TF_HDR_SIZE];
2737 uint8_t hdr[SMB2_HDR_BODY];
2738 struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
2739 uint8_t body[1];
2742 static NTSTATUS smbd_smb2_send_break(struct smbd_server_connection *sconn,
2743 struct smbXsrv_session *session,
2744 struct smbXsrv_tcon *tcon,
2745 const uint8_t *body,
2746 size_t body_len)
2748 struct smbd_smb2_send_break_state *state;
2749 struct smbXsrv_connection *xconn = sconn->conn;
2750 bool do_encryption = session->global->encryption_required;
2751 uint64_t nonce_high = 0;
2752 uint64_t nonce_low = 0;
2753 NTSTATUS status;
2754 size_t statelen;
2756 if (tcon->global->encryption_required) {
2757 do_encryption = true;
2760 statelen = offsetof(struct smbd_smb2_send_break_state, body) +
2761 body_len;
2763 state = talloc_zero_size(sconn, statelen);
2764 if (state == NULL) {
2765 return NT_STATUS_NO_MEMORY;
2767 talloc_set_name_const(state, "struct smbd_smb2_send_break_state");
2768 state->sconn = sconn;
2770 if (do_encryption) {
2771 nonce_high = session->nonce_high;
2772 nonce_low = session->nonce_low;
2774 session->nonce_low += 1;
2775 if (session->nonce_low == 0) {
2776 session->nonce_low += 1;
2777 session->nonce_high += 1;
2781 SIVAL(state->tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2782 SBVAL(state->tf, SMB2_TF_NONCE+0, nonce_low);
2783 SBVAL(state->tf, SMB2_TF_NONCE+8, nonce_high);
2784 SBVAL(state->tf, SMB2_TF_SESSION_ID, session->global->session_wire_id);
2786 SIVAL(state->hdr, 0, SMB2_MAGIC);
2787 SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2788 SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
2789 SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
2790 SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
2791 SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
2792 SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
2793 SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
2794 SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
2795 SIVAL(state->hdr, SMB2_HDR_PID, 0);
2796 SIVAL(state->hdr, SMB2_HDR_TID, 0);
2797 SBVAL(state->hdr, SMB2_HDR_SESSION_ID, 0);
2798 memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
2800 state->vector[0] = (struct iovec) {
2801 .iov_base = state->nbt_hdr,
2802 .iov_len = sizeof(state->nbt_hdr)
2805 if (do_encryption) {
2806 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2807 .iov_base = state->tf,
2808 .iov_len = sizeof(state->tf)
2810 } else {
2811 state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
2812 .iov_base = NULL,
2813 .iov_len = 0
2817 state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
2818 .iov_base = state->hdr,
2819 .iov_len = sizeof(state->hdr)
2822 memcpy(state->body, body, body_len);
2824 state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
2825 .iov_base = state->body,
2826 .iov_len = body_len /* no sizeof(state->body) .. :-) */
2830 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
2833 smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2835 if (do_encryption) {
2836 DATA_BLOB encryption_key = session->global->encryption_key;
2838 status = smb2_signing_encrypt_pdu(encryption_key,
2839 xconn->protocol,
2840 &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2841 SMBD_SMB2_NUM_IOV_PER_REQ);
2842 if (!NT_STATUS_IS_OK(status)) {
2843 return status;
2847 state->queue_entry.mem_ctx = state;
2848 state->queue_entry.vector = state->vector;
2849 state->queue_entry.count = ARRAY_SIZE(state->vector);
2850 DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry, NULL);
2851 xconn->smb2.send_queue_len++;
2853 status = smbd_smb2_flush_send_queue(xconn);
2854 if (!NT_STATUS_IS_OK(status)) {
2855 return status;
2858 return NT_STATUS_OK;
2861 NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
2862 struct smbXsrv_session *session,
2863 struct smbXsrv_tcon *tcon,
2864 struct smbXsrv_open *op,
2865 uint8_t oplock_level)
2867 uint8_t body[0x18];
2869 SSVAL(body, 0x00, sizeof(body));
2870 SCVAL(body, 0x02, oplock_level);
2871 SCVAL(body, 0x03, 0); /* reserved */
2872 SIVAL(body, 0x04, 0); /* reserved */
2873 SBVAL(body, 0x08, op->global->open_persistent_id);
2874 SBVAL(body, 0x10, op->global->open_volatile_id);
2876 return smbd_smb2_send_break(sconn, session, tcon, body, sizeof(body));
2879 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
2881 NTSTATUS status;
2882 uint32_t flags;
2883 uint64_t file_id_persistent;
2884 uint64_t file_id_volatile;
2885 struct smbXsrv_open *op = NULL;
2886 struct files_struct *fsp = NULL;
2887 const uint8_t *body = NULL;
2890 * This is only called with a pktbuf
2891 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
2892 * bytes
2895 if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
2896 /* Transform header. Cannot recvfile. */
2897 return false;
2899 if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
2900 /* Not SMB2. Normal error path will cope. */
2901 return false;
2903 if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
2904 /* Not SMB2. Normal error path will cope. */
2905 return false;
2907 if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
2908 /* Needs to be a WRITE. */
2909 return false;
2911 if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
2912 /* Chained. Cannot recvfile. */
2913 return false;
2915 flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
2916 if (flags & SMB2_HDR_FLAG_CHAINED) {
2917 /* Chained. Cannot recvfile. */
2918 return false;
2920 if (flags & SMB2_HDR_FLAG_SIGNED) {
2921 /* Signed. Cannot recvfile. */
2922 return false;
2925 body = &state->pktbuf[SMB2_HDR_BODY];
2927 file_id_persistent = BVAL(body, 0x10);
2928 file_id_volatile = BVAL(body, 0x18);
2930 status = smb2srv_open_lookup(state->req->sconn->conn,
2931 file_id_persistent,
2932 file_id_volatile,
2933 0, /* now */
2934 &op);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 return false;
2939 fsp = op->compat;
2940 if (fsp == NULL) {
2941 return false;
2943 if (fsp->conn == NULL) {
2944 return false;
2947 if (IS_IPC(fsp->conn)) {
2948 return false;
2950 if (IS_PRINT(fsp->conn)) {
2951 return false;
2954 DEBUG(10,("Doing recvfile write len = %u\n",
2955 (unsigned int)(state->pktfull - state->pktlen)));
2957 return true;
2960 static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn)
2962 struct smbXsrv_connection *xconn = sconn->conn;
2963 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
2964 size_t max_send_queue_len;
2965 size_t cur_send_queue_len;
2967 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2969 * we're not supposed to do any io
2971 return NT_STATUS_OK;
2974 if (state->req != NULL) {
2976 * if there is already a tstream_readv_pdu
2977 * pending, we are done.
2979 return NT_STATUS_OK;
2982 max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
2983 cur_send_queue_len = xconn->smb2.send_queue_len;
2985 if (cur_send_queue_len > max_send_queue_len) {
2987 * if we have a lot of requests to send,
2988 * we wait until they are on the wire until we
2989 * ask for the next request.
2991 return NT_STATUS_OK;
2994 /* ask for the next request */
2995 ZERO_STRUCTP(state);
2996 state->req = smbd_smb2_request_allocate(xconn);
2997 if (state->req == NULL) {
2998 return NT_STATUS_NO_MEMORY;
3000 state->req->sconn = sconn;
3001 state->req->xconn = xconn;
3002 state->min_recv_size = lp_min_receive_file_size();
3004 TEVENT_FD_READABLE(xconn->transport.fde);
3006 return NT_STATUS_OK;
3009 void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
3010 uint8_t *inbuf, size_t size)
3012 NTSTATUS status;
3013 struct smbd_smb2_request *req = NULL;
3015 DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
3016 (unsigned int)size));
3018 status = smbd_initialize_smb2(sconn);
3019 if (!NT_STATUS_IS_OK(status)) {
3020 smbd_server_connection_terminate(sconn, nt_errstr(status));
3021 return;
3024 status = smbd_smb2_request_create(sconn, inbuf, size, &req);
3025 if (!NT_STATUS_IS_OK(status)) {
3026 smbd_server_connection_terminate(sconn, nt_errstr(status));
3027 return;
3030 status = smbd_smb2_request_validate(req);
3031 if (!NT_STATUS_IS_OK(status)) {
3032 smbd_server_connection_terminate(sconn, nt_errstr(status));
3033 return;
3036 status = smbd_smb2_request_setup_out(req);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 smbd_server_connection_terminate(sconn, nt_errstr(status));
3039 return;
3042 status = smbd_smb2_request_dispatch(req);
3043 if (!NT_STATUS_IS_OK(status)) {
3044 smbd_server_connection_terminate(sconn, nt_errstr(status));
3045 return;
3048 status = smbd_smb2_request_next_incoming(sconn);
3049 if (!NT_STATUS_IS_OK(status)) {
3050 smbd_server_connection_terminate(sconn, nt_errstr(status));
3051 return;
3054 sconn->num_requests++;
3057 static int socket_error_from_errno(int ret,
3058 int sys_errno,
3059 bool *retry)
3061 *retry = false;
3063 if (ret >= 0) {
3064 return 0;
3067 if (ret != -1) {
3068 return EIO;
3071 if (sys_errno == 0) {
3072 return EIO;
3075 if (sys_errno == EINTR) {
3076 *retry = true;
3077 return sys_errno;
3080 if (sys_errno == EINPROGRESS) {
3081 *retry = true;
3082 return sys_errno;
3085 if (sys_errno == EAGAIN) {
3086 *retry = true;
3087 return sys_errno;
3090 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
3091 if (sys_errno == ENOMEM) {
3092 *retry = true;
3093 return sys_errno;
3096 #ifdef EWOULDBLOCK
3097 #if EWOULDBLOCK != EAGAIN
3098 if (sys_errno == EWOULDBLOCK) {
3099 *retry = true;
3100 return sys_errno;
3102 #endif
3103 #endif
3105 return sys_errno;
3108 static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
3110 int ret;
3111 int err;
3112 bool retry;
3114 if (xconn->smb2.send_queue == NULL) {
3115 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3116 return NT_STATUS_OK;
3119 while (xconn->smb2.send_queue != NULL) {
3120 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
3122 if (e->sendfile_header != NULL) {
3123 size_t size = 0;
3124 size_t i = 0;
3125 uint8_t *buf;
3127 for (i=0; i < e->count; i++) {
3128 size += e->vector[i].iov_len;
3131 if (size <= e->sendfile_header->length) {
3132 buf = e->sendfile_header->data;
3133 } else {
3134 buf = talloc_array(e->mem_ctx, uint8_t, size);
3135 if (buf == NULL) {
3136 return NT_STATUS_NO_MEMORY;
3140 size = 0;
3141 for (i=0; i < e->count; i++) {
3142 memcpy(buf+size,
3143 e->vector[i].iov_base,
3144 e->vector[i].iov_len);
3145 size += e->vector[i].iov_len;
3148 e->sendfile_header->data = buf;
3149 e->sendfile_header->length = size;
3150 e->count = 0;
3152 xconn->smb2.send_queue_len--;
3153 DLIST_REMOVE(xconn->smb2.send_queue, e);
3155 * This triggers the sendfile path via
3156 * the destructor.
3158 talloc_free(e->mem_ctx);
3159 continue;
3162 ret = writev(xconn->transport.sock, e->vector, e->count);
3163 if (ret == 0) {
3164 /* propagate end of file */
3165 return NT_STATUS_INTERNAL_ERROR;
3167 err = socket_error_from_errno(ret, errno, &retry);
3168 if (retry) {
3169 /* retry later */
3170 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3171 return NT_STATUS_OK;
3173 if (err != 0) {
3174 return map_nt_error_from_unix_common(err);
3176 while (ret > 0) {
3177 if (ret < e->vector[0].iov_len) {
3178 uint8_t *base;
3179 base = (uint8_t *)e->vector[0].iov_base;
3180 base += ret;
3181 e->vector[0].iov_base = (void *)base;
3182 e->vector[0].iov_len -= ret;
3183 break;
3185 ret -= e->vector[0].iov_len;
3186 e->vector += 1;
3187 e->count -= 1;
3191 * there're maybe some empty vectors at the end
3192 * which we need to skip, otherwise we would get
3193 * ret == 0 from the readv() call and return EPIPE
3195 while (e->count > 0) {
3196 if (e->vector[0].iov_len > 0) {
3197 break;
3199 e->vector += 1;
3200 e->count -= 1;
3203 if (e->count > 0) {
3204 /* we have more to write */
3205 TEVENT_FD_WRITEABLE(xconn->transport.fde);
3206 return NT_STATUS_OK;
3209 xconn->smb2.send_queue_len--;
3210 DLIST_REMOVE(xconn->smb2.send_queue, e);
3211 talloc_free(e->mem_ctx);
3214 return NT_STATUS_OK;
3217 static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
3218 uint16_t fde_flags)
3220 struct smbd_server_connection *sconn = xconn->sconn;
3221 struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
3222 struct smbd_smb2_request *req = NULL;
3223 size_t min_recvfile_size = UINT32_MAX;
3224 int ret;
3225 int err;
3226 bool retry;
3227 NTSTATUS status;
3228 NTTIME now;
3230 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
3232 * we're not supposed to do any io
3234 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3235 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
3236 return NT_STATUS_OK;
3239 if (fde_flags & TEVENT_FD_WRITE) {
3240 status = smbd_smb2_flush_send_queue(xconn);
3241 if (!NT_STATUS_IS_OK(status)) {
3242 return status;
3246 if (!(fde_flags & TEVENT_FD_READ)) {
3247 return NT_STATUS_OK;
3250 if (state->req == NULL) {
3251 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
3252 return NT_STATUS_OK;
3255 again:
3256 if (!state->hdr.done) {
3257 state->hdr.done = true;
3259 state->vector.iov_base = (void *)state->hdr.nbt;
3260 state->vector.iov_len = NBT_HDR_SIZE;
3263 ret = readv(xconn->transport.sock, &state->vector, 1);
3264 if (ret == 0) {
3265 /* propagate end of file */
3266 return NT_STATUS_END_OF_FILE;
3268 err = socket_error_from_errno(ret, errno, &retry);
3269 if (retry) {
3270 /* retry later */
3271 TEVENT_FD_READABLE(xconn->transport.fde);
3272 return NT_STATUS_OK;
3274 if (err != 0) {
3275 return map_nt_error_from_unix_common(err);
3278 if (ret < state->vector.iov_len) {
3279 uint8_t *base;
3280 base = (uint8_t *)state->vector.iov_base;
3281 base += ret;
3282 state->vector.iov_base = (void *)base;
3283 state->vector.iov_len -= ret;
3284 /* we have more to read */
3285 TEVENT_FD_READABLE(xconn->transport.fde);
3286 return NT_STATUS_OK;
3289 if (state->pktlen > 0) {
3290 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
3292 * Not a possible receivefile write.
3293 * Read the rest of the data.
3295 state->doing_receivefile = false;
3297 state->pktbuf = talloc_realloc(state->req,
3298 state->pktbuf,
3299 uint8_t,
3300 state->pktfull);
3301 if (state->pktbuf == NULL) {
3302 return NT_STATUS_NO_MEMORY;
3305 state->vector.iov_base = (void *)(state->pktbuf +
3306 state->pktlen);
3307 state->vector.iov_len = (state->pktfull -
3308 state->pktlen);
3310 state->pktlen = state->pktfull;
3311 goto again;
3315 * Either this is a receivefile write so we've
3316 * done a short read, or if not we have all the data.
3318 goto got_full;
3322 * Now we analyze the NBT header
3324 if (state->hdr.nbt[0] != 0x00) {
3325 state->min_recv_size = 0;
3327 state->pktfull = smb2_len(state->hdr.nbt);
3328 if (state->pktfull == 0) {
3329 goto got_full;
3332 if (state->min_recv_size != 0) {
3333 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3334 min_recvfile_size += state->min_recv_size;
3337 if (state->pktfull > min_recvfile_size) {
3339 * Might be a receivefile write. Read the SMB2 HEADER +
3340 * SMB2_WRITE header first. Set 'doing_receivefile'
3341 * as we're *attempting* receivefile write. If this
3342 * turns out not to be a SMB2_WRITE request or otherwise
3343 * not suitable then we'll just read the rest of the data
3344 * the next time this function is called.
3346 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
3347 state->doing_receivefile = true;
3348 } else {
3349 state->pktlen = state->pktfull;
3352 state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
3353 if (state->pktbuf == NULL) {
3354 return NT_STATUS_NO_MEMORY;
3357 state->vector.iov_base = (void *)state->pktbuf;
3358 state->vector.iov_len = state->pktlen;
3360 goto again;
3362 got_full:
3364 if (state->hdr.nbt[0] != 0x00) {
3365 DEBUG(1,("ignore NBT[0x%02X] msg\n",
3366 state->hdr.nbt[0]));
3368 req = state->req;
3369 ZERO_STRUCTP(state);
3370 state->req = req;
3371 state->min_recv_size = lp_min_receive_file_size();
3372 req = NULL;
3373 goto again;
3376 req = state->req;
3377 state->req = NULL;
3379 req->request_time = timeval_current();
3380 now = timeval_to_nttime(&req->request_time);
3382 status = smbd_smb2_inbuf_parse_compound(xconn,
3383 now,
3384 state->pktbuf,
3385 state->pktlen,
3386 req,
3387 &req->in.vector,
3388 &req->in.vector_count);
3389 if (!NT_STATUS_IS_OK(status)) {
3390 return status;
3393 if (state->doing_receivefile) {
3394 req->smb1req = talloc_zero(req, struct smb_request);
3395 if (req->smb1req == NULL) {
3396 return NT_STATUS_NO_MEMORY;
3398 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
3401 ZERO_STRUCTP(state);
3403 req->current_idx = 1;
3405 DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
3406 req->current_idx, req->in.vector_count));
3408 status = smbd_smb2_request_validate(req);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 return status;
3413 status = smbd_smb2_request_setup_out(req);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 return status;
3418 status = smbd_smb2_request_dispatch(req);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 return status;
3423 sconn->num_requests++;
3425 /* The timeout_processing function isn't run nearly
3426 often enough to implement 'max log size' without
3427 overrunning the size of the file by many megabytes.
3428 This is especially true if we are running at debug
3429 level 10. Checking every 50 SMB2s is a nice
3430 tradeoff of performance vs log file size overrun. */
3432 if ((sconn->num_requests % 50) == 0 &&
3433 need_to_check_log_size()) {
3434 change_to_root_user();
3435 check_log_size();
3438 status = smbd_smb2_request_next_incoming(sconn);
3439 if (!NT_STATUS_IS_OK(status)) {
3440 return status;
3443 return NT_STATUS_OK;
3446 static void smbd_smb2_connection_handler(struct tevent_context *ev,
3447 struct tevent_fd *fde,
3448 uint16_t flags,
3449 void *private_data)
3451 struct smbXsrv_connection *xconn =
3452 talloc_get_type_abort(private_data,
3453 struct smbXsrv_connection);
3454 struct smbd_server_connection *sconn = xconn->sconn;
3455 NTSTATUS status;
3457 status = smbd_smb2_io_handler(xconn, flags);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 smbd_server_connection_terminate(sconn, nt_errstr(status));
3460 return;