Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Core SMB2 server
4 :
5 : Copyright (C) Stefan Metzmacher 2009
6 : Copyright (C) Jeremy Allison 2010
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "system/network.h"
24 : #include "smbd/smbd.h"
25 : #include "smbd/globals.h"
26 : #include "smbd/smbXsrv_open.h"
27 : #include "lib/param/param.h"
28 : #include "../libcli/smb/smb_common.h"
29 : #include "../lib/tsocket/tsocket.h"
30 : #include "../lib/util/tevent_ntstatus.h"
31 : #include "smbprofile.h"
32 : #include "../lib/util/bitmap.h"
33 : #include "../librpc/gen_ndr/krb5pac.h"
34 : #include "lib/util/iov_buf.h"
35 : #include "auth.h"
36 : #include "libcli/smb/smbXcli_base.h"
37 : #include "source3/lib/substitute.h"
38 :
39 : #if defined(LINUX)
40 : /* SIOCOUTQ TIOCOUTQ are the same */
41 : #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
42 : #define __HAVE_TCP_INFO_RTO 1
43 : #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
44 : #elif defined(FREEBSD)
45 : #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
46 : #define __HAVE_TCP_INFO_RTO 1
47 : #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
48 : #endif
49 :
50 : #include "lib/crypto/gnutls_helpers.h"
51 : #include <gnutls/gnutls.h>
52 : #include <gnutls/crypto.h>
53 :
54 : #undef DBGC_CLASS
55 : #define DBGC_CLASS DBGC_SMB2
56 :
57 : static void smbd_smb2_connection_handler(struct tevent_context *ev,
58 : struct tevent_fd *fde,
59 : uint16_t flags,
60 : void *private_data);
61 : static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
62 :
63 : static const struct smbd_smb2_dispatch_table {
64 : uint16_t opcode;
65 : const char *name;
66 : bool need_session;
67 : bool need_tcon;
68 : bool as_root;
69 : uint16_t fileid_ofs;
70 : bool modify;
71 : } smbd_smb2_table[] = {
72 : #define _OP(o) .opcode = o, .name = #o
73 : {
74 : _OP(SMB2_OP_NEGPROT),
75 : .as_root = true,
76 : },{
77 : _OP(SMB2_OP_SESSSETUP),
78 : .as_root = true,
79 : },{
80 : _OP(SMB2_OP_LOGOFF),
81 : .need_session = true,
82 : .as_root = true,
83 : },{
84 : _OP(SMB2_OP_TCON),
85 : .need_session = true,
86 : /*
87 : * This call needs to be run as root.
88 : *
89 : * smbd_smb2_request_process_tcon()
90 : * calls make_connection_snum(), which will call
91 : * change_to_user(), when needed.
92 : */
93 : .as_root = true,
94 : },{
95 : _OP(SMB2_OP_TDIS),
96 : .need_session = true,
97 : .need_tcon = true,
98 : .as_root = true,
99 : },{
100 : _OP(SMB2_OP_CREATE),
101 : .need_session = true,
102 : .need_tcon = true,
103 : },{
104 : _OP(SMB2_OP_CLOSE),
105 : .need_session = true,
106 : .need_tcon = true,
107 : .fileid_ofs = 0x08,
108 : },{
109 : _OP(SMB2_OP_FLUSH),
110 : .need_session = true,
111 : .need_tcon = true,
112 : .fileid_ofs = 0x08,
113 : },{
114 : _OP(SMB2_OP_READ),
115 : .need_session = true,
116 : .need_tcon = true,
117 : .fileid_ofs = 0x10,
118 : },{
119 : _OP(SMB2_OP_WRITE),
120 : .need_session = true,
121 : .need_tcon = true,
122 : .fileid_ofs = 0x10,
123 : .modify = true,
124 : },{
125 : _OP(SMB2_OP_LOCK),
126 : .need_session = true,
127 : .need_tcon = true,
128 : .fileid_ofs = 0x08,
129 : },{
130 : _OP(SMB2_OP_IOCTL),
131 : .need_session = true,
132 : .need_tcon = true,
133 : .fileid_ofs = 0x08,
134 : .modify = true,
135 : },{
136 : _OP(SMB2_OP_CANCEL),
137 : .as_root = true,
138 : },{
139 : _OP(SMB2_OP_KEEPALIVE),
140 : .as_root = true,
141 : },{
142 : _OP(SMB2_OP_QUERY_DIRECTORY),
143 : .need_session = true,
144 : .need_tcon = true,
145 : .fileid_ofs = 0x08,
146 : },{
147 : _OP(SMB2_OP_NOTIFY),
148 : .need_session = true,
149 : .need_tcon = true,
150 : .fileid_ofs = 0x08,
151 : },{
152 : _OP(SMB2_OP_GETINFO),
153 : .need_session = true,
154 : .need_tcon = true,
155 : .fileid_ofs = 0x18,
156 : },{
157 : _OP(SMB2_OP_SETINFO),
158 : .need_session = true,
159 : .need_tcon = true,
160 : .fileid_ofs = 0x10,
161 : .modify = true,
162 : },{
163 : _OP(SMB2_OP_BREAK),
164 : .need_session = true,
165 : .need_tcon = true,
166 : /*
167 : * we do not set
168 : * .fileid_ofs here
169 : * as LEASE breaks does not
170 : * have a file id
171 : */
172 : }
173 : };
174 :
175 0 : const char *smb2_opcode_name(uint16_t opcode)
176 : {
177 0 : if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
178 0 : return "Bad SMB2 opcode";
179 : }
180 0 : return smbd_smb2_table[opcode].name;
181 : }
182 :
183 159518 : static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
184 : {
185 159518 : const struct smbd_smb2_dispatch_table *ret = NULL;
186 :
187 159518 : if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
188 0 : return NULL;
189 : }
190 :
191 159518 : ret = &smbd_smb2_table[opcode];
192 :
193 159518 : SMB_ASSERT(ret->opcode == opcode);
194 :
195 159518 : return ret;
196 : }
197 :
198 0 : static void print_req_vectors(const struct smbd_smb2_request *req)
199 : {
200 : int i;
201 :
202 0 : for (i = 0; i < req->in.vector_count; i++) {
203 0 : dbgtext("\treq->in.vector[%u].iov_len = %u\n",
204 : (unsigned int)i,
205 0 : (unsigned int)req->in.vector[i].iov_len);
206 : }
207 0 : for (i = 0; i < req->out.vector_count; i++) {
208 0 : dbgtext("\treq->out.vector[%u].iov_len = %u\n",
209 : (unsigned int)i,
210 0 : (unsigned int)req->out.vector[i].iov_len);
211 : }
212 0 : }
213 :
214 1813 : bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
215 : {
216 1813 : if (size < (4 + SMB2_HDR_BODY)) {
217 18 : return false;
218 : }
219 :
220 1795 : if (IVAL(inbuf, 4) != SMB2_MAGIC) {
221 118 : return false;
222 : }
223 :
224 1677 : return true;
225 : }
226 :
227 2620 : bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
228 : {
229 2620 : return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
230 : }
231 :
232 802 : bool smbd_smb2_is_last_in_compound(const struct smbd_smb2_request *req)
233 : {
234 1604 : return (req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ ==
235 802 : req->in.vector_count);
236 : }
237 :
238 5046 : static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
239 : uint64_t expected_seq_low)
240 : {
241 : int rc;
242 :
243 5046 : xconn->smb2.credits.seq_low = expected_seq_low;
244 5046 : xconn->smb2.credits.seq_range = 1;
245 5046 : xconn->smb2.credits.granted = 1;
246 5046 : xconn->smb2.credits.max = lp_smb2_max_credits();
247 10092 : xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
248 5046 : xconn->smb2.credits.max);
249 5046 : if (xconn->smb2.credits.bitmap == NULL) {
250 0 : return NT_STATUS_NO_MEMORY;
251 : }
252 :
253 5046 : tevent_fd_set_close_fn(xconn->transport.fde, NULL);
254 5046 : TALLOC_FREE(xconn->transport.fde);
255 :
256 5046 : xconn->transport.fde = tevent_add_fd(
257 : xconn->client->raw_ev_ctx,
258 : xconn,
259 : xconn->transport.sock,
260 : TEVENT_FD_READ,
261 : smbd_smb2_connection_handler,
262 : xconn);
263 5046 : if (xconn->transport.fde == NULL) {
264 0 : close(xconn->transport.sock);
265 0 : xconn->transport.sock = -1;
266 0 : return NT_STATUS_NO_MEMORY;
267 : }
268 5046 : tevent_fd_set_auto_close(xconn->transport.fde);
269 :
270 : /* Ensure child is set to non-blocking mode */
271 5046 : rc = set_blocking(xconn->transport.sock, false);
272 5046 : if (rc < 0) {
273 0 : return NT_STATUS_INTERNAL_ERROR;
274 : }
275 :
276 5046 : return NT_STATUS_OK;
277 : }
278 :
279 : #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
280 : #define _smb2_setlen(_buf,len) do { \
281 : uint8_t *buf = (uint8_t *)_buf; \
282 : buf[0] = 0; \
283 : buf[1] = ((len)&0xFF0000)>>16; \
284 : buf[2] = ((len)&0xFF00)>>8; \
285 : buf[3] = (len)&0xFF; \
286 : } while (0)
287 :
288 339039 : static bool smb2_setup_nbt_length(struct iovec *vector, int count)
289 : {
290 : ssize_t len;
291 :
292 339039 : if (count == 0) {
293 0 : return false;
294 : }
295 :
296 339039 : len = iov_buflen(vector+1, count-1);
297 :
298 339039 : if ((len == -1) || (len > 0xFFFFFF)) {
299 0 : return false;
300 : }
301 :
302 339039 : _smb2_setlen(vector[0].iov_base, len);
303 339039 : return true;
304 : }
305 :
306 162136 : static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
307 : {
308 162136 : TALLOC_FREE(req->first_enc_key);
309 162136 : TALLOC_FREE(req->last_sign_key);
310 162136 : return 0;
311 : }
312 :
313 0 : void smb2_request_set_async_internal(struct smbd_smb2_request *req,
314 : bool async_internal)
315 : {
316 0 : req->async_internal = async_internal;
317 0 : }
318 :
319 162136 : static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
320 : {
321 : TALLOC_CTX *mem_pool;
322 : struct smbd_smb2_request *req;
323 :
324 : #if 0
325 : /* Enable this to find subtle valgrind errors. */
326 : mem_pool = talloc_init("smbd_smb2_request_allocate");
327 : #else
328 162136 : mem_pool = talloc_tos();
329 : #endif
330 162136 : if (mem_pool == NULL) {
331 0 : return NULL;
332 : }
333 :
334 162136 : req = talloc_zero(mem_pool, struct smbd_smb2_request);
335 162136 : if (req == NULL) {
336 0 : talloc_free(mem_pool);
337 0 : return NULL;
338 : }
339 162136 : talloc_reparent(mem_pool, mem_ctx, req);
340 : #if 0
341 : TALLOC_FREE(mem_pool);
342 : #endif
343 :
344 162136 : req->last_session_id = UINT64_MAX;
345 162136 : req->last_tid = UINT32_MAX;
346 :
347 162136 : talloc_set_destructor(req, smbd_smb2_request_destructor);
348 :
349 162136 : return req;
350 : }
351 :
352 159518 : static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
353 : NTTIME now,
354 : uint8_t *buf,
355 : size_t buflen,
356 : struct smbd_smb2_request *req,
357 : struct iovec **piov,
358 : int *pnum_iov)
359 : {
360 159518 : TALLOC_CTX *mem_ctx = req;
361 : struct iovec *iov;
362 159518 : int num_iov = 1;
363 159518 : size_t taken = 0;
364 159518 : uint8_t *first_hdr = buf;
365 159518 : size_t verified_buflen = 0;
366 159518 : uint8_t *tf = NULL;
367 159518 : size_t tf_len = 0;
368 :
369 : /*
370 : * Note: index '0' is reserved for the transport protocol
371 : */
372 159518 : iov = req->in._vector;
373 :
374 319036 : while (taken < buflen) {
375 159518 : size_t len = buflen - taken;
376 159518 : uint8_t *hdr = first_hdr + taken;
377 : struct iovec *cur;
378 : size_t full_size;
379 : size_t next_command_ofs;
380 : uint16_t body_size;
381 159518 : uint8_t *body = NULL;
382 : uint32_t dyn_size;
383 159518 : uint8_t *dyn = NULL;
384 159518 : struct iovec *iov_alloc = NULL;
385 :
386 159518 : if (iov != req->in._vector) {
387 0 : iov_alloc = iov;
388 : }
389 :
390 159518 : if (verified_buflen > taken) {
391 0 : len = verified_buflen - taken;
392 : } else {
393 159518 : tf = NULL;
394 159518 : tf_len = 0;
395 : }
396 :
397 159518 : if (len < 4) {
398 0 : DEBUG(10, ("%d bytes left, expected at least %d\n",
399 : (int)len, 4));
400 0 : goto inval;
401 : }
402 159518 : if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
403 624 : struct smbXsrv_session *s = NULL;
404 : uint64_t uid;
405 : struct iovec tf_iov[2];
406 : NTSTATUS status;
407 : size_t enc_len;
408 :
409 624 : if (xconn->protocol < PROTOCOL_SMB3_00) {
410 0 : DEBUG(10, ("Got SMB2_TRANSFORM header, "
411 : "but dialect[0x%04X] is used\n",
412 : xconn->smb2.server.dialect));
413 0 : goto inval;
414 : }
415 :
416 624 : if (xconn->smb2.server.cipher == 0) {
417 0 : DEBUG(10, ("Got SMB2_TRANSFORM header, "
418 : "but not negotiated "
419 : "client[0x%08X] server[0x%08X]\n",
420 : xconn->smb2.client.capabilities,
421 : xconn->smb2.server.capabilities));
422 0 : goto inval;
423 : }
424 :
425 624 : if (len < SMB2_TF_HDR_SIZE) {
426 0 : DEBUG(1, ("%d bytes left, expected at least %d\n",
427 : (int)len, SMB2_TF_HDR_SIZE));
428 0 : goto inval;
429 : }
430 624 : tf = hdr;
431 624 : tf_len = SMB2_TF_HDR_SIZE;
432 624 : taken += tf_len;
433 :
434 624 : hdr = first_hdr + taken;
435 624 : enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
436 624 : uid = BVAL(tf, SMB2_TF_SESSION_ID);
437 :
438 624 : if (len < SMB2_TF_HDR_SIZE + enc_len) {
439 0 : DEBUG(1, ("%d bytes left, expected at least %d\n",
440 : (int)len,
441 : (int)(SMB2_TF_HDR_SIZE + enc_len)));
442 0 : goto inval;
443 : }
444 :
445 624 : status = smb2srv_session_lookup_conn(xconn, uid, now,
446 : &s);
447 624 : if (s == NULL) {
448 0 : status = smb2srv_session_lookup_global(xconn->client,
449 : uid, req, &s);
450 : }
451 624 : if (s == NULL) {
452 0 : DEBUG(1, ("invalid session[%llu] in "
453 : "SMB2_TRANSFORM header\n",
454 : (unsigned long long)uid));
455 0 : TALLOC_FREE(iov_alloc);
456 0 : return NT_STATUS_USER_SESSION_DELETED;
457 : }
458 :
459 624 : tf_iov[0].iov_base = (void *)tf;
460 624 : tf_iov[0].iov_len = tf_len;
461 624 : tf_iov[1].iov_base = (void *)hdr;
462 624 : tf_iov[1].iov_len = enc_len;
463 :
464 624 : status = smb2_signing_decrypt_pdu(s->global->decryption_key,
465 : tf_iov, 2);
466 624 : if (!NT_STATUS_IS_OK(status)) {
467 0 : TALLOC_FREE(iov_alloc);
468 0 : return status;
469 : }
470 :
471 624 : verified_buflen = taken + enc_len;
472 624 : len = enc_len;
473 : }
474 :
475 : /*
476 : * We need the header plus the body length field
477 : */
478 :
479 159518 : if (len < SMB2_HDR_BODY + 2) {
480 :
481 0 : if ((len == 5) &&
482 0 : (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
483 0 : lp_parm_bool(-1, "smbd", "suicide mode", false)) {
484 0 : uint8_t exitcode = CVAL(hdr, 4);
485 0 : DBG_WARNING("SUICIDE: Exiting immediately "
486 : "with code %"PRIu8"\n",
487 : exitcode);
488 0 : exit(exitcode);
489 : }
490 :
491 0 : DEBUG(10, ("%d bytes left, expected at least %d\n",
492 : (int)len, SMB2_HDR_BODY));
493 0 : goto inval;
494 : }
495 159518 : if (IVAL(hdr, 0) != SMB2_MAGIC) {
496 0 : DEBUG(10, ("Got non-SMB2 PDU: %x\n",
497 : IVAL(hdr, 0)));
498 0 : goto inval;
499 : }
500 159518 : if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
501 0 : DEBUG(10, ("Got HDR len %d, expected %d\n",
502 : SVAL(hdr, 4), SMB2_HDR_BODY));
503 0 : goto inval;
504 : }
505 :
506 159518 : full_size = len;
507 159518 : next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
508 159518 : body_size = SVAL(hdr, SMB2_HDR_BODY);
509 :
510 159518 : if (next_command_ofs != 0) {
511 0 : if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
512 0 : goto inval;
513 : }
514 0 : if (next_command_ofs > full_size) {
515 0 : goto inval;
516 : }
517 0 : full_size = next_command_ofs;
518 : }
519 159518 : if (body_size < 2) {
520 0 : goto inval;
521 : }
522 159518 : body_size &= 0xfffe;
523 :
524 159518 : if (body_size > (full_size - SMB2_HDR_BODY)) {
525 : /*
526 : * let the caller handle the error
527 : */
528 0 : body_size = full_size - SMB2_HDR_BODY;
529 : }
530 159518 : body = hdr + SMB2_HDR_BODY;
531 159518 : dyn = body + body_size;
532 159518 : dyn_size = full_size - (SMB2_HDR_BODY + body_size);
533 :
534 159518 : if (num_iov >= ARRAY_SIZE(req->in._vector)) {
535 0 : struct iovec *iov_tmp = NULL;
536 :
537 0 : iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
538 : struct iovec,
539 : num_iov +
540 : SMBD_SMB2_NUM_IOV_PER_REQ);
541 0 : if (iov_tmp == NULL) {
542 0 : TALLOC_FREE(iov_alloc);
543 0 : return NT_STATUS_NO_MEMORY;
544 : }
545 :
546 0 : if (iov_alloc == NULL) {
547 0 : memcpy(iov_tmp,
548 0 : req->in._vector,
549 : sizeof(req->in._vector));
550 : }
551 :
552 0 : iov = iov_tmp;
553 : }
554 159518 : cur = &iov[num_iov];
555 159518 : num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
556 :
557 159518 : cur[SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
558 159518 : cur[SMBD_SMB2_TF_IOV_OFS].iov_len = tf_len;
559 159518 : cur[SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
560 159518 : cur[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
561 159518 : cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
562 159518 : cur[SMBD_SMB2_BODY_IOV_OFS].iov_len = body_size;
563 159518 : cur[SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
564 159518 : cur[SMBD_SMB2_DYN_IOV_OFS].iov_len = dyn_size;
565 :
566 159518 : taken += full_size;
567 : }
568 :
569 159518 : *piov = iov;
570 159518 : *pnum_iov = num_iov;
571 159518 : return NT_STATUS_OK;
572 :
573 0 : inval:
574 0 : if (iov != req->in._vector) {
575 0 : TALLOC_FREE(iov);
576 : }
577 0 : return NT_STATUS_INVALID_PARAMETER;
578 : }
579 :
580 5046 : static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
581 : const uint8_t *_inpdu, size_t size,
582 : struct smbd_smb2_request **_req)
583 : {
584 5046 : struct smbd_server_connection *sconn = xconn->client->sconn;
585 : struct smbd_smb2_request *req;
586 : uint32_t protocol_version;
587 5046 : uint8_t *inpdu = NULL;
588 5046 : const uint8_t *inhdr = NULL;
589 : uint16_t cmd;
590 : uint32_t next_command_ofs;
591 : NTSTATUS status;
592 : NTTIME now;
593 :
594 5046 : if (size < (SMB2_HDR_BODY + 2)) {
595 0 : DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
596 0 : return NT_STATUS_INVALID_PARAMETER;
597 : }
598 :
599 5046 : inhdr = _inpdu;
600 :
601 5046 : protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
602 5046 : if (protocol_version != SMB2_MAGIC) {
603 0 : DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
604 : protocol_version));
605 0 : return NT_STATUS_INVALID_PARAMETER;
606 : }
607 :
608 5046 : cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
609 5046 : if (cmd != SMB2_OP_NEGPROT) {
610 0 : DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
611 : cmd));
612 0 : return NT_STATUS_INVALID_PARAMETER;
613 : }
614 :
615 5046 : next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
616 5046 : if (next_command_ofs != 0) {
617 0 : DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
618 : next_command_ofs));
619 0 : return NT_STATUS_INVALID_PARAMETER;
620 : }
621 :
622 5046 : req = smbd_smb2_request_allocate(xconn);
623 5046 : if (req == NULL) {
624 0 : return NT_STATUS_NO_MEMORY;
625 : }
626 5046 : req->sconn = sconn;
627 5046 : req->xconn = xconn;
628 :
629 5046 : inpdu = talloc_memdup(req, _inpdu, size);
630 5046 : if (inpdu == NULL) {
631 0 : return NT_STATUS_NO_MEMORY;
632 : }
633 :
634 5046 : req->request_time = timeval_current();
635 5046 : now = timeval_to_nttime(&req->request_time);
636 :
637 5046 : status = smbd_smb2_inbuf_parse_compound(xconn,
638 : now,
639 : inpdu,
640 : size,
641 : req, &req->in.vector,
642 : &req->in.vector_count);
643 5046 : if (!NT_STATUS_IS_OK(status)) {
644 0 : TALLOC_FREE(req);
645 0 : return status;
646 : }
647 :
648 5046 : req->current_idx = 1;
649 :
650 5046 : *_req = req;
651 5046 : return NT_STATUS_OK;
652 : }
653 :
654 707908 : static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
655 : uint64_t message_id, uint64_t seq_id)
656 : {
657 707908 : struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
658 : unsigned int offset;
659 : uint64_t seq_tmp;
660 :
661 707908 : seq_tmp = xconn->smb2.credits.seq_low;
662 707908 : if (seq_id < seq_tmp) {
663 0 : DBGC_ERR(DBGC_SMB2_CREDITS,
664 : "smb2_validate_sequence_number: bad message_id "
665 : "%llu (sequence id %llu) "
666 : "(granted = %u, low = %llu, range = %u)\n",
667 : (unsigned long long)message_id,
668 : (unsigned long long)seq_id,
669 : (unsigned int)xconn->smb2.credits.granted,
670 : (unsigned long long)xconn->smb2.credits.seq_low,
671 : (unsigned int)xconn->smb2.credits.seq_range);
672 0 : return false;
673 : }
674 :
675 707908 : seq_tmp += xconn->smb2.credits.seq_range;
676 707908 : if (seq_id >= seq_tmp) {
677 0 : DBGC_ERR(DBGC_SMB2_CREDITS,
678 : "smb2_validate_sequence_number: bad message_id "
679 : "%llu (sequence id %llu) "
680 : "(granted = %u, low = %llu, range = %u)\n",
681 : (unsigned long long)message_id,
682 : (unsigned long long)seq_id,
683 : (unsigned int)xconn->smb2.credits.granted,
684 : (unsigned long long)xconn->smb2.credits.seq_low,
685 : (unsigned int)xconn->smb2.credits.seq_range);
686 0 : return false;
687 : }
688 :
689 707908 : offset = seq_id % xconn->smb2.credits.max;
690 :
691 707908 : if (bitmap_query(credits_bm, offset)) {
692 0 : DBGC_ERR(DBGC_SMB2_CREDITS,
693 : "smb2_validate_sequence_number: duplicate message_id "
694 : "%llu (sequence id %llu) "
695 : "(granted = %u, low = %llu, range = %u) "
696 : "(bm offset %u)\n",
697 : (unsigned long long)message_id,
698 : (unsigned long long)seq_id,
699 : (unsigned int)xconn->smb2.credits.granted,
700 : (unsigned long long)xconn->smb2.credits.seq_low,
701 : (unsigned int)xconn->smb2.credits.seq_range,
702 : offset);
703 0 : return false;
704 : }
705 :
706 : /* Mark the message_ids as seen in the bitmap. */
707 707908 : bitmap_set(credits_bm, offset);
708 :
709 707908 : if (seq_id != xconn->smb2.credits.seq_low) {
710 0 : return true;
711 : }
712 :
713 : /*
714 : * Move the window forward by all the message_id's
715 : * already seen.
716 : */
717 1415816 : while (bitmap_query(credits_bm, offset)) {
718 707908 : DBGC_DEBUG(DBGC_SMB2_CREDITS,
719 : "smb2_validate_sequence_number: clearing "
720 : "id %llu (position %u) from bitmap\n",
721 : (unsigned long long)(xconn->smb2.credits.seq_low),
722 : offset);
723 707908 : bitmap_clear(credits_bm, offset);
724 :
725 707908 : xconn->smb2.credits.seq_low += 1;
726 707908 : xconn->smb2.credits.seq_range -= 1;
727 707908 : offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
728 : }
729 :
730 707908 : return true;
731 : }
732 :
733 159518 : static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
734 : const uint8_t *inhdr)
735 : {
736 159518 : uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
737 159518 : uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
738 159518 : uint16_t credit_charge = 1;
739 : uint64_t i;
740 :
741 159518 : if (opcode == SMB2_OP_CANCEL) {
742 : /* SMB2_CANCEL requests by definition resend messageids. */
743 18 : return true;
744 : }
745 :
746 159500 : if (xconn->smb2.credits.multicredit) {
747 152081 : credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
748 152081 : credit_charge = MAX(credit_charge, 1);
749 : }
750 :
751 159500 : DEBUGC(11,
752 : DBGC_SMB2_CREDITS,
753 : ("smb2_validate_message_id: mid %llu (charge %llu), "
754 : "credits_granted %llu, "
755 : "seqnum low/range: %llu/%llu\n",
756 : (unsigned long long) message_id,
757 : (unsigned long long) credit_charge,
758 : (unsigned long long) xconn->smb2.credits.granted,
759 : (unsigned long long) xconn->smb2.credits.seq_low,
760 : (unsigned long long) xconn->smb2.credits.seq_range));
761 :
762 159500 : if (xconn->smb2.credits.granted < credit_charge) {
763 0 : DBGC_ERR(DBGC_SMB2_CREDITS,
764 : "smb2_validate_message_id: client used more "
765 : "credits than granted, mid %llu, charge %llu, "
766 : "credits_granted %llu, "
767 : "seqnum low/range: %llu/%llu\n",
768 : (unsigned long long) message_id,
769 : (unsigned long long) credit_charge,
770 : (unsigned long long) xconn->smb2.credits.granted,
771 : (unsigned long long) xconn->smb2.credits.seq_low,
772 : (unsigned long long) xconn->smb2.credits.seq_range);
773 0 : return false;
774 : }
775 :
776 : /*
777 : * now check the message ids
778 : *
779 : * for multi-credit requests we need to check all current mid plus
780 : * the implicit mids caused by the credit charge
781 : * e.g. current mid = 15, charge 5 => mark 15-19 as used
782 : */
783 :
784 867408 : for (i = 0; i <= (credit_charge-1); i++) {
785 707908 : uint64_t id = message_id + i;
786 : bool ok;
787 :
788 707908 : DEBUGC(11,
789 : DBGC_SMB2_CREDITS,
790 : ("Iterating mid %llu charge %u (sequence %llu)\n",
791 : (unsigned long long)message_id,
792 : credit_charge,
793 : (unsigned long long)id));
794 :
795 707908 : ok = smb2_validate_sequence_number(xconn, message_id, id);
796 707908 : if (!ok) {
797 0 : return false;
798 : }
799 : }
800 :
801 : /* substract used credits */
802 159500 : xconn->smb2.credits.granted -= credit_charge;
803 :
804 159500 : return true;
805 : }
806 :
807 159518 : static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
808 : {
809 : int count;
810 : int idx;
811 :
812 159518 : count = req->in.vector_count;
813 :
814 159518 : if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
815 : /* It's not a SMB2 request */
816 0 : return NT_STATUS_INVALID_PARAMETER;
817 : }
818 :
819 319036 : for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
820 159518 : struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
821 159518 : struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
822 159518 : const uint8_t *inhdr = NULL;
823 :
824 159518 : if (hdr->iov_len != SMB2_HDR_BODY) {
825 0 : return NT_STATUS_INVALID_PARAMETER;
826 : }
827 :
828 159518 : if (body->iov_len < 2) {
829 0 : return NT_STATUS_INVALID_PARAMETER;
830 : }
831 :
832 159518 : inhdr = (const uint8_t *)hdr->iov_base;
833 :
834 : /* Check the SMB2 header */
835 159518 : if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
836 0 : return NT_STATUS_INVALID_PARAMETER;
837 : }
838 :
839 159518 : if (!smb2_validate_message_id(req->xconn, inhdr)) {
840 0 : return NT_STATUS_INVALID_PARAMETER;
841 : }
842 : }
843 :
844 159518 : return NT_STATUS_OK;
845 : }
846 :
847 179521 : static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
848 : const struct iovec *in_vector,
849 : struct iovec *out_vector)
850 : {
851 179521 : const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
852 179521 : uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
853 179521 : uint16_t credit_charge = 1;
854 : uint16_t credits_requested;
855 : uint32_t out_flags;
856 : uint16_t cmd;
857 : NTSTATUS out_status;
858 179521 : uint16_t credits_granted = 0;
859 : uint64_t credits_possible;
860 : uint16_t current_max_credits;
861 :
862 : /*
863 : * first we grant only 1/16th of the max range.
864 : *
865 : * Windows also starts with the 1/16th and then grants
866 : * more later. I was only able to trigger higher
867 : * values, when using a very high credit charge.
868 : *
869 : * TODO: scale up depending on load, free memory
870 : * or other stuff.
871 : * Maybe also on the relationship between number
872 : * of requests and the used sequence number.
873 : * Which means we would grant more credits
874 : * for client which use multi credit requests.
875 : *
876 : * The above is what Windows Server < 2016 is doing,
877 : * but new servers use all credits (8192 by default).
878 : */
879 179521 : current_max_credits = xconn->smb2.credits.max;
880 179521 : current_max_credits = MAX(current_max_credits, 1);
881 :
882 179521 : if (xconn->smb2.credits.multicredit) {
883 176757 : credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
884 176757 : credit_charge = MAX(credit_charge, 1);
885 : }
886 :
887 179521 : cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
888 179521 : credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
889 179521 : credits_requested = MAX(credits_requested, 1);
890 179521 : out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
891 179521 : out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
892 :
893 179521 : SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
894 :
895 179521 : if (xconn->smb2.credits.max < credit_charge) {
896 0 : smbd_server_connection_terminate(xconn,
897 : "client error: credit charge > max credits\n");
898 0 : return;
899 : }
900 :
901 179521 : if (out_flags & SMB2_HDR_FLAG_ASYNC) {
902 : /*
903 : * In case we already send an async interim
904 : * response, we should not grant
905 : * credits on the final response.
906 : */
907 20071 : credits_granted = 0;
908 : } else {
909 159450 : uint16_t additional_possible =
910 159450 : xconn->smb2.credits.max - credit_charge;
911 159450 : uint16_t additional_max = 0;
912 159450 : uint16_t additional_credits = credits_requested - 1;
913 :
914 159450 : switch (cmd) {
915 8315 : case SMB2_OP_NEGPROT:
916 8315 : break;
917 6767 : case SMB2_OP_SESSSETUP:
918 : /*
919 : * Windows 2012 RC1 starts to grant
920 : * additional credits
921 : * with a successful session setup
922 : */
923 6767 : if (NT_STATUS_IS_OK(out_status)) {
924 4826 : additional_max = xconn->smb2.credits.max;
925 : }
926 6767 : break;
927 144368 : default:
928 : /*
929 : * Windows Server < 2016 and older Samba versions
930 : * used to only grant additional credits in
931 : * chunks of 32 credits.
932 : *
933 : * But we match Windows Server 2016 and grant
934 : * all credits as requested.
935 : */
936 144368 : additional_max = xconn->smb2.credits.max;
937 144368 : break;
938 : }
939 :
940 159450 : additional_max = MIN(additional_max, additional_possible);
941 159450 : additional_credits = MIN(additional_credits, additional_max);
942 :
943 159450 : credits_granted = credit_charge + additional_credits;
944 : }
945 :
946 : /*
947 : * sequence numbers should not wrap
948 : *
949 : * 1. calculate the possible credits until
950 : * the sequence numbers start to wrap on 64-bit.
951 : *
952 : * 2. UINT64_MAX is used for Break Notifications.
953 : *
954 : * 2. truncate the possible credits to the maximum
955 : * credits we want to grant to the client in total.
956 : *
957 : * 3. remove the range we'll already granted to the client
958 : * this makes sure the client consumes the lowest sequence
959 : * number, before we can grant additional credits.
960 : */
961 179521 : credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
962 179521 : if (credits_possible > 0) {
963 : /* remove UINT64_MAX */
964 179521 : credits_possible -= 1;
965 : }
966 179521 : credits_possible = MIN(credits_possible, current_max_credits);
967 179521 : credits_possible -= xconn->smb2.credits.seq_range;
968 :
969 179521 : credits_granted = MIN(credits_granted, credits_possible);
970 :
971 179521 : SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
972 179521 : xconn->smb2.credits.granted += credits_granted;
973 179521 : xconn->smb2.credits.seq_range += credits_granted;
974 :
975 179521 : DBGC_DEBUG(DBGC_SMB2_CREDITS,
976 : "smb2_set_operation_credit: requested %u, charge %u, "
977 : "granted %u, current possible/max %u/%u, "
978 : "total granted/max/low/range %u/%u/%llu/%u\n",
979 : (unsigned int)credits_requested,
980 : (unsigned int)credit_charge,
981 : (unsigned int)credits_granted,
982 : (unsigned int)credits_possible,
983 : (unsigned int)current_max_credits,
984 : (unsigned int)xconn->smb2.credits.granted,
985 : (unsigned int)xconn->smb2.credits.max,
986 : (unsigned long long)xconn->smb2.credits.seq_low,
987 : (unsigned int)xconn->smb2.credits.seq_range);
988 : }
989 :
990 159450 : static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
991 : struct smbd_smb2_request *outreq)
992 : {
993 : int count, idx;
994 159450 : uint16_t total_credits = 0;
995 :
996 159450 : count = outreq->out.vector_count;
997 :
998 318900 : for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
999 159450 : struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
1000 159450 : struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
1001 159450 : uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
1002 :
1003 159450 : smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
1004 :
1005 : /* To match Windows, count up what we
1006 : just granted. */
1007 159450 : total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
1008 : /* Set to zero in all but the last reply. */
1009 159450 : if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
1010 0 : SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
1011 : } else {
1012 159450 : SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
1013 : }
1014 : }
1015 159450 : }
1016 :
1017 154051 : DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
1018 : {
1019 154051 : if (req->current_idx <= 1) {
1020 154051 : if (size <= sizeof(req->out._body)) {
1021 154051 : return data_blob_const(req->out._body, size);
1022 : }
1023 : }
1024 :
1025 0 : return data_blob_talloc(req, NULL, size);
1026 : }
1027 :
1028 159518 : static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
1029 : {
1030 159518 : struct smbXsrv_connection *xconn = req->xconn;
1031 : TALLOC_CTX *mem_ctx;
1032 : struct iovec *vector;
1033 : int count;
1034 : int idx;
1035 : bool ok;
1036 :
1037 159518 : count = req->in.vector_count;
1038 159518 : if (count <= ARRAY_SIZE(req->out._vector)) {
1039 159518 : mem_ctx = req;
1040 159518 : vector = req->out._vector;
1041 : } else {
1042 0 : vector = talloc_zero_array(req, struct iovec, count);
1043 0 : if (vector == NULL) {
1044 0 : return NT_STATUS_NO_MEMORY;
1045 : }
1046 0 : mem_ctx = vector;
1047 : }
1048 :
1049 159518 : vector[0].iov_base = req->out.nbt_hdr;
1050 159518 : vector[0].iov_len = 4;
1051 159518 : SIVAL(req->out.nbt_hdr, 0, 0);
1052 :
1053 319036 : for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
1054 159518 : struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
1055 159518 : const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
1056 159518 : uint8_t *outhdr = NULL;
1057 159518 : uint8_t *outbody = NULL;
1058 159518 : uint32_t next_command_ofs = 0;
1059 159518 : struct iovec *current = &vector[idx];
1060 :
1061 159518 : if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
1062 : /* we have a next command -
1063 : * setup for the error case. */
1064 0 : next_command_ofs = SMB2_HDR_BODY + 9;
1065 : }
1066 :
1067 159518 : if (idx == 1) {
1068 159518 : outhdr = req->out._hdr;
1069 : } else {
1070 0 : outhdr = talloc_zero_array(mem_ctx, uint8_t,
1071 : OUTVEC_ALLOC_SIZE);
1072 0 : if (outhdr == NULL) {
1073 0 : return NT_STATUS_NO_MEMORY;
1074 : }
1075 : }
1076 :
1077 159518 : outbody = outhdr + SMB2_HDR_BODY;
1078 :
1079 : /*
1080 : * SMBD_SMB2_TF_IOV_OFS might be used later
1081 : */
1082 159518 : current[SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
1083 159518 : current[SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
1084 :
1085 159518 : current[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)outhdr;
1086 159518 : current[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1087 :
1088 159518 : current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
1089 159518 : current[SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
1090 :
1091 159518 : current[SMBD_SMB2_DYN_IOV_OFS].iov_base = NULL;
1092 159518 : current[SMBD_SMB2_DYN_IOV_OFS].iov_len = 0;
1093 :
1094 : /* setup the SMB2 header */
1095 159518 : SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
1096 159518 : SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
1097 159518 : SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
1098 : SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
1099 159518 : SIVAL(outhdr, SMB2_HDR_STATUS,
1100 : NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
1101 159518 : SSVAL(outhdr, SMB2_HDR_OPCODE,
1102 : SVAL(inhdr, SMB2_HDR_OPCODE));
1103 159518 : SIVAL(outhdr, SMB2_HDR_FLAGS,
1104 : IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
1105 159518 : SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
1106 159518 : SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
1107 : BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
1108 159518 : SIVAL(outhdr, SMB2_HDR_PID,
1109 : IVAL(inhdr, SMB2_HDR_PID));
1110 159518 : SIVAL(outhdr, SMB2_HDR_TID,
1111 : IVAL(inhdr, SMB2_HDR_TID));
1112 159518 : SBVAL(outhdr, SMB2_HDR_SESSION_ID,
1113 : BVAL(inhdr, SMB2_HDR_SESSION_ID));
1114 159518 : memcpy(outhdr + SMB2_HDR_SIGNATURE,
1115 159518 : inhdr + SMB2_HDR_SIGNATURE, 16);
1116 :
1117 : /* setup error body header */
1118 159518 : SSVAL(outbody, 0x00, 0x08 + 1);
1119 159518 : SSVAL(outbody, 0x02, 0);
1120 159518 : SIVAL(outbody, 0x04, 0);
1121 : }
1122 :
1123 159518 : req->out.vector = vector;
1124 159518 : req->out.vector_count = count;
1125 :
1126 : /* setup the length of the NBT packet */
1127 159518 : ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
1128 159518 : if (!ok) {
1129 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1130 : }
1131 :
1132 159518 : DLIST_ADD_END(xconn->smb2.requests, req);
1133 :
1134 159518 : return NT_STATUS_OK;
1135 : }
1136 :
1137 5251 : bool smbXsrv_server_multi_channel_enabled(void)
1138 : {
1139 5251 : bool enabled = lp_server_multi_channel_support();
1140 : #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
1141 : bool forced = false;
1142 : struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
1143 : bool unspecified = lpcfg_parm_is_unspecified(lp_ctx, "server multi channel support");
1144 : if (unspecified) {
1145 : enabled = false;
1146 : }
1147 : /*
1148 : * If we don't have support from the kernel
1149 : * to ask for the un-acked number of bytes
1150 : * in the socket send queue, we better
1151 : * don't support multi-channel.
1152 : */
1153 : forced = lp_parm_bool(-1, "force", "server multi channel support", false);
1154 : if (enabled && !forced) {
1155 : D_NOTICE("'server multi channel support' enabled "
1156 : "but not supported on %s (%s)\n",
1157 : SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
1158 : DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
1159 : "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
1160 : enabled = false;
1161 : }
1162 : TALLOC_FREE(lp_ctx);
1163 : #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
1164 5251 : return enabled;
1165 : }
1166 :
1167 0 : static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
1168 : uint32_t *_rto_usecs)
1169 : {
1170 : /*
1171 : * Define an Retransmission Timeout
1172 : * of 1 second, if there's no way for the
1173 : * kernel to tell us the current value.
1174 : */
1175 0 : uint32_t rto_usecs = 1000000;
1176 :
1177 : #ifdef __HAVE_TCP_INFO_RTO
1178 : {
1179 : struct tcp_info info;
1180 0 : socklen_t ilen = sizeof(info);
1181 : int ret;
1182 :
1183 0 : ZERO_STRUCT(info);
1184 0 : ret = getsockopt(xconn->transport.sock,
1185 : IPPROTO_TCP, TCP_INFO,
1186 : (void *)&info, &ilen);
1187 0 : if (ret != 0) {
1188 0 : int saved_errno = errno;
1189 0 : NTSTATUS status = map_nt_error_from_unix(errno);
1190 0 : DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
1191 : saved_errno, strerror(saved_errno),
1192 : nt_errstr(status));
1193 0 : return status;
1194 : }
1195 :
1196 0 : DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
1197 : (unsigned)info.tcpi_rto,
1198 : (unsigned)info.tcpi_rtt,
1199 : (unsigned)info.tcpi_rttvar);
1200 0 : rto_usecs = info.tcpi_rto;
1201 : }
1202 : #endif /* __HAVE_TCP_INFO_RTO */
1203 :
1204 0 : rto_usecs = MAX(rto_usecs, 200000); /* at least 0.2s */
1205 0 : rto_usecs = MIN(rto_usecs, 1000000); /* at max 1.0s */
1206 0 : *_rto_usecs = rto_usecs;
1207 0 : return NT_STATUS_OK;
1208 : }
1209 :
1210 0 : static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
1211 : uint64_t *_acked_bytes)
1212 : {
1213 : /*
1214 : * Unless the kernel has an interface
1215 : * to reveal the number of un-acked bytes
1216 : * in the socket send queue, we'll assume
1217 : * everything is already acked.
1218 : *
1219 : * But that would mean that we better don't
1220 : * pretent to support multi-channel.
1221 : */
1222 0 : uint64_t unacked_bytes = 0;
1223 :
1224 0 : *_acked_bytes = 0;
1225 :
1226 0 : if (xconn->ack.force_unacked_timeout) {
1227 : /*
1228 : * Smbtorture tries to test channel failures...
1229 : * Just pretend nothing was acked...
1230 : */
1231 0 : DBG_INFO("Simulating channel failure: "
1232 : "xconn->ack.unacked_bytes[%llu]\n",
1233 : (unsigned long long)xconn->ack.unacked_bytes);
1234 0 : return NT_STATUS_OK;
1235 : }
1236 :
1237 : #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
1238 : {
1239 0 : int value = 0;
1240 : int ret;
1241 :
1242 : /*
1243 : * If we have kernel support to get
1244 : * the number of bytes waiting in
1245 : * the socket's send queue, we
1246 : * use that in order to find out
1247 : * the number of unacked bytes.
1248 : */
1249 0 : ret = ioctl(xconn->transport.sock,
1250 : __IOCTL_SEND_QUEUE_SIZE_OPCODE,
1251 : &value);
1252 0 : if (ret != 0) {
1253 0 : int saved_errno = errno;
1254 0 : NTSTATUS status = map_nt_error_from_unix(saved_errno);
1255 0 : DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
1256 : "errno %d (%s) - %s\n",
1257 : saved_errno, strerror(saved_errno),
1258 : nt_errstr(status));
1259 0 : return status;
1260 : }
1261 :
1262 0 : if (value < 0) {
1263 0 : DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
1264 : (unsigned long long)xconn->ack.unacked_bytes,
1265 : value);
1266 0 : return NT_STATUS_INTERNAL_ERROR;
1267 : }
1268 0 : unacked_bytes = value;
1269 : }
1270 : #endif
1271 0 : if (xconn->ack.unacked_bytes == 0) {
1272 0 : xconn->ack.unacked_bytes = unacked_bytes;
1273 0 : return NT_STATUS_OK;
1274 : }
1275 :
1276 0 : if (xconn->ack.unacked_bytes < unacked_bytes) {
1277 0 : DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
1278 : (unsigned long long)xconn->ack.unacked_bytes,
1279 : (unsigned long long)unacked_bytes);
1280 0 : return NT_STATUS_INTERNAL_ERROR;
1281 : }
1282 :
1283 0 : *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
1284 0 : xconn->ack.unacked_bytes = unacked_bytes;
1285 0 : return NT_STATUS_OK;
1286 : }
1287 :
1288 10602 : static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
1289 : NTSTATUS status)
1290 : {
1291 10602 : struct smbd_smb2_send_queue *e = NULL;
1292 10602 : struct smbd_smb2_send_queue *n = NULL;
1293 :
1294 13030 : for (e = *queue; e != NULL; e = n) {
1295 2428 : n = e->next;
1296 :
1297 2428 : DLIST_REMOVE(*queue, e);
1298 2428 : if (e->ack.req != NULL) {
1299 0 : tevent_req_nterror(e->ack.req, status);
1300 : }
1301 : }
1302 10602 : }
1303 :
1304 0 : static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
1305 : uint64_t acked_bytes)
1306 : {
1307 0 : struct smbd_smb2_send_queue *e = NULL;
1308 0 : struct smbd_smb2_send_queue *n = NULL;
1309 :
1310 0 : for (e = *queue; e != NULL; e = n) {
1311 : bool expired;
1312 :
1313 0 : n = e->next;
1314 :
1315 0 : if (e->ack.req == NULL) {
1316 0 : continue;
1317 : }
1318 :
1319 0 : if (e->ack.required_acked_bytes <= acked_bytes) {
1320 0 : e->ack.required_acked_bytes = 0;
1321 0 : DLIST_REMOVE(*queue, e);
1322 0 : tevent_req_done(e->ack.req);
1323 0 : continue;
1324 : }
1325 0 : e->ack.required_acked_bytes -= acked_bytes;
1326 :
1327 0 : expired = timeval_expired(&e->ack.timeout);
1328 0 : if (expired) {
1329 0 : return NT_STATUS_IO_TIMEOUT;
1330 : }
1331 : }
1332 :
1333 0 : return NT_STATUS_OK;
1334 : }
1335 :
1336 0 : static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
1337 : {
1338 0 : uint64_t acked_bytes = 0;
1339 : NTSTATUS status;
1340 :
1341 0 : status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1342 0 : if (!NT_STATUS_IS_OK(status)) {
1343 0 : return status;
1344 : }
1345 :
1346 0 : status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
1347 0 : if (!NT_STATUS_IS_OK(status)) {
1348 0 : return status;
1349 : }
1350 :
1351 0 : status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
1352 0 : if (!NT_STATUS_IS_OK(status)) {
1353 0 : return status;
1354 : }
1355 :
1356 0 : return NT_STATUS_OK;
1357 : }
1358 :
1359 0 : static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
1360 : {
1361 : struct smbXsrv_connection *xconn =
1362 0 : tevent_req_callback_data(subreq,
1363 : struct smbXsrv_connection);
1364 0 : struct smbXsrv_client *client = xconn->client;
1365 : struct timeval next_check;
1366 : NTSTATUS status;
1367 : bool ok;
1368 :
1369 0 : xconn->ack.checker_subreq = NULL;
1370 :
1371 0 : ok = tevent_wakeup_recv(subreq);
1372 0 : TALLOC_FREE(subreq);
1373 0 : if (!ok) {
1374 0 : smbd_server_connection_terminate(xconn,
1375 : "tevent_wakeup_recv() failed");
1376 0 : return;
1377 : }
1378 :
1379 0 : status = smbd_smb2_check_ack_queue(xconn);
1380 0 : if (!NT_STATUS_IS_OK(status)) {
1381 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
1382 0 : return;
1383 : }
1384 :
1385 0 : next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1386 0 : xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1387 : client->raw_ev_ctx,
1388 : next_check);
1389 0 : if (xconn->ack.checker_subreq == NULL) {
1390 0 : smbd_server_connection_terminate(xconn,
1391 : "tevent_wakeup_send() failed");
1392 0 : return;
1393 : }
1394 0 : tevent_req_set_callback(xconn->ack.checker_subreq,
1395 : smbXsrv_connection_ack_checker,
1396 : xconn);
1397 : }
1398 :
1399 5046 : static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
1400 : {
1401 5046 : struct smbXsrv_connection *xconn = NULL;
1402 :
1403 10144 : for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1404 : struct timeval next_check;
1405 5098 : uint64_t acked_bytes = 0;
1406 : NTSTATUS status;
1407 :
1408 : /*
1409 : * A new 'pending break cycle' starts
1410 : * with a first pending break and lasts until
1411 : * all pending breaks are finished.
1412 : *
1413 : * This is typically a very short time,
1414 : * the value of one retransmission timeout.
1415 : */
1416 :
1417 5098 : if (client->pending_breaks == NULL) {
1418 : /*
1419 : * No more pending breaks, remove a pending
1420 : * checker timer
1421 : */
1422 5098 : TALLOC_FREE(xconn->ack.checker_subreq);
1423 5098 : continue;
1424 : }
1425 :
1426 0 : if (xconn->ack.checker_subreq != NULL) {
1427 : /*
1428 : * The cycle already started =>
1429 : * nothing todo
1430 : */
1431 0 : continue;
1432 : }
1433 :
1434 : /*
1435 : * Get the current retransmission timeout value.
1436 : *
1437 : * It may change over time, but fetching it once
1438 : * per 'pending break' cycled should be enough.
1439 : */
1440 0 : status = smbXsrv_connection_get_rto_usecs(xconn,
1441 : &xconn->ack.rto_usecs);
1442 0 : if (!NT_STATUS_IS_OK(status)) {
1443 0 : return status;
1444 : }
1445 :
1446 : /*
1447 : * At the start of the cycle we reset the
1448 : * unacked_bytes counter (first to 0 and
1449 : * within smbXsrv_connection_get_acked_bytes()
1450 : * to the current value in the kernel
1451 : * send queue.
1452 : */
1453 0 : xconn->ack.unacked_bytes = 0;
1454 0 : status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
1455 0 : if (!NT_STATUS_IS_OK(status)) {
1456 0 : return status;
1457 : }
1458 :
1459 : /*
1460 : * We setup a timer in order to check for
1461 : * acked bytes after one retransmission timeout.
1462 : *
1463 : * The code that sets up the send_queue.ack.timeout
1464 : * uses a multiple of the retransmission timeout.
1465 : */
1466 0 : next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
1467 0 : xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
1468 : client->raw_ev_ctx,
1469 : next_check);
1470 0 : if (xconn->ack.checker_subreq == NULL) {
1471 0 : return NT_STATUS_NO_MEMORY;
1472 : }
1473 0 : tevent_req_set_callback(xconn->ack.checker_subreq,
1474 : smbXsrv_connection_ack_checker,
1475 : xconn);
1476 : }
1477 :
1478 5046 : return NT_STATUS_OK;
1479 : }
1480 :
1481 15313 : void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
1482 : NTSTATUS status)
1483 : {
1484 15313 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1485 10012 : return;
1486 : }
1487 :
1488 5301 : xconn->transport.status = status;
1489 5301 : TALLOC_FREE(xconn->transport.fde);
1490 5301 : if (xconn->transport.sock != -1) {
1491 5301 : xconn->transport.sock = -1;
1492 : }
1493 5301 : smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
1494 5301 : smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
1495 5301 : xconn->smb2.send_queue_len = 0;
1496 5301 : DO_PROFILE_INC(disconnect);
1497 : }
1498 :
1499 5031 : size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
1500 : {
1501 5031 : struct smbXsrv_connection *xconn = NULL;
1502 5031 : size_t num_ok = 0;
1503 :
1504 10114 : for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
1505 5083 : if (NT_STATUS_IS_OK(xconn->transport.status)) {
1506 52 : num_ok++;
1507 : }
1508 : }
1509 :
1510 5031 : return num_ok;
1511 : }
1512 :
1513 : struct smbXsrv_connection_shutdown_state {
1514 : struct smbXsrv_connection *xconn;
1515 : };
1516 :
1517 : static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
1518 :
1519 50 : static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
1520 : struct tevent_context *ev,
1521 : struct smbXsrv_connection *xconn)
1522 : {
1523 50 : struct tevent_req *req = NULL;
1524 50 : struct smbXsrv_connection_shutdown_state *state = NULL;
1525 50 : struct tevent_req *subreq = NULL;
1526 50 : size_t len = 0;
1527 50 : struct smbd_smb2_request *preq = NULL;
1528 : NTSTATUS status;
1529 :
1530 : /*
1531 : * The caller should have called
1532 : * smbXsrv_connection_disconnect_transport() before.
1533 : */
1534 50 : SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
1535 50 : SMB_ASSERT(xconn->transport.terminating);
1536 50 : SMB_ASSERT(xconn->transport.shutdown_wait_queue == NULL);
1537 :
1538 50 : req = tevent_req_create(mem_ctx, &state,
1539 : struct smbXsrv_connection_shutdown_state);
1540 50 : if (req == NULL) {
1541 0 : return NULL;
1542 : }
1543 :
1544 50 : state->xconn = xconn;
1545 50 : tevent_req_defer_callback(req, ev);
1546 :
1547 50 : xconn->transport.shutdown_wait_queue =
1548 50 : tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
1549 50 : if (tevent_req_nomem(xconn->transport.shutdown_wait_queue, req)) {
1550 0 : return tevent_req_post(req, ev);
1551 : }
1552 :
1553 50 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1554 : /*
1555 : * Now wait until the request is finished.
1556 : *
1557 : * We don't set a callback, as we just want to block the
1558 : * wait queue and the talloc_free() of the request will
1559 : * remove the item from the wait queue.
1560 : *
1561 : * Note that we don't cancel the requests here
1562 : * in order to keep the replay detection logic correct.
1563 : *
1564 : * However if we teardown the last channel of
1565 : * a connection, we'll call some logic via
1566 : * smbXsrv_session_disconnect_xconn()
1567 : * -> smbXsrv_session_disconnect_xconn_callback()
1568 : * -> smbXsrv_session_remove_channel()
1569 : * -> smb2srv_session_shutdown_send()
1570 : * will indeed cancel the request.
1571 : */
1572 0 : subreq = tevent_queue_wait_send(preq, ev,
1573 : xconn->transport.shutdown_wait_queue);
1574 0 : if (tevent_req_nomem(subreq, req)) {
1575 0 : return tevent_req_post(req, ev);
1576 : }
1577 : }
1578 :
1579 : /*
1580 : * This may attach sessions with num_channels == 0
1581 : * to xconn->transport.shutdown_wait_queue.
1582 : */
1583 50 : status = smbXsrv_session_disconnect_xconn(xconn);
1584 50 : if (tevent_req_nterror(req, status)) {
1585 0 : return tevent_req_post(req, ev);
1586 : }
1587 :
1588 50 : len = tevent_queue_length(xconn->transport.shutdown_wait_queue);
1589 50 : if (len == 0) {
1590 48 : tevent_req_done(req);
1591 48 : return tevent_req_post(req, ev);
1592 : }
1593 :
1594 : /*
1595 : * Now we add our own waiter to the end of the queue,
1596 : * this way we get notified when all pending requests are finished
1597 : * and send to the socket.
1598 : */
1599 2 : subreq = tevent_queue_wait_send(state, ev, xconn->transport.shutdown_wait_queue);
1600 2 : if (tevent_req_nomem(subreq, req)) {
1601 0 : return tevent_req_post(req, ev);
1602 : }
1603 2 : tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
1604 :
1605 2 : return req;
1606 : }
1607 :
1608 2 : static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
1609 : {
1610 : struct tevent_req *req =
1611 2 : tevent_req_callback_data(subreq,
1612 : struct tevent_req);
1613 : struct smbXsrv_connection_shutdown_state *state =
1614 2 : tevent_req_data(req,
1615 : struct smbXsrv_connection_shutdown_state);
1616 2 : struct smbXsrv_connection *xconn = state->xconn;
1617 :
1618 2 : tevent_queue_wait_recv(subreq);
1619 2 : TALLOC_FREE(subreq);
1620 :
1621 2 : tevent_req_done(req);
1622 : /*
1623 : * make sure the xconn pointer is still valid,
1624 : * it should as we used tevent_req_defer_callback()
1625 : */
1626 2 : SMB_ASSERT(xconn->transport.terminating);
1627 2 : }
1628 :
1629 50 : static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
1630 : {
1631 : struct smbXsrv_connection_shutdown_state *state =
1632 50 : tevent_req_data(req,
1633 : struct smbXsrv_connection_shutdown_state);
1634 50 : struct smbXsrv_connection *xconn = state->xconn;
1635 : /*
1636 : * make sure the xconn pointer is still valid,
1637 : * it should as we used tevent_req_defer_callback()
1638 : */
1639 50 : SMB_ASSERT(xconn->transport.terminating);
1640 50 : return tevent_req_simple_recv_ntstatus(req);
1641 : }
1642 :
1643 50 : static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
1644 : {
1645 : struct smbXsrv_connection *xconn =
1646 50 : tevent_req_callback_data(subreq,
1647 : struct smbXsrv_connection);
1648 50 : struct smbXsrv_client *client = xconn->client;
1649 : NTSTATUS status;
1650 :
1651 50 : status = smbXsrv_connection_shutdown_recv(subreq);
1652 50 : TALLOC_FREE(subreq);
1653 50 : if (!NT_STATUS_IS_OK(status)) {
1654 0 : exit_server("smbXsrv_connection_shutdown_recv failed");
1655 : }
1656 :
1657 50 : DLIST_REMOVE(client->connections, xconn);
1658 50 : TALLOC_FREE(xconn);
1659 50 : }
1660 :
1661 5031 : void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
1662 : const char *reason,
1663 : const char *location)
1664 : {
1665 5031 : struct smbXsrv_client *client = xconn->client;
1666 5031 : size_t num_ok = 0;
1667 :
1668 : /*
1669 : * Make sure that no new request will be able to use this session.
1670 : *
1671 : * smbXsrv_connection_disconnect_transport() might be called already,
1672 : * but calling it again is a no-op.
1673 : */
1674 5031 : smbXsrv_connection_disconnect_transport(xconn,
1675 5031 : NT_STATUS_CONNECTION_DISCONNECTED);
1676 :
1677 5031 : num_ok = smbXsrv_client_valid_connections(client);
1678 :
1679 5031 : if (xconn->transport.terminating) {
1680 0 : DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
1681 : smbXsrv_connection_dbg(xconn), num_ok,
1682 : reason, location);
1683 0 : return;
1684 : }
1685 5031 : xconn->transport.terminating = true;
1686 :
1687 5031 : DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
1688 : smbXsrv_connection_dbg(xconn), num_ok,
1689 : reason, location);
1690 :
1691 5031 : if (xconn->has_cluster_movable_ip) {
1692 : /*
1693 : * If the connection has a movable cluster public address
1694 : * we disconnect all client connections,
1695 : * as the public address might be moved to
1696 : * a different node.
1697 : *
1698 : * In future we may recheck which node currently
1699 : * holds this address, but for now we keep it simple.
1700 : */
1701 0 : smbd_server_disconnect_client_ex(xconn->client,
1702 : reason,
1703 : location);
1704 0 : return;
1705 : }
1706 :
1707 5031 : if (num_ok != 0) {
1708 50 : struct tevent_req *subreq = NULL;
1709 :
1710 50 : subreq = smbXsrv_connection_shutdown_send(client,
1711 : client->raw_ev_ctx,
1712 : xconn);
1713 50 : if (subreq == NULL) {
1714 0 : exit_server("smbXsrv_connection_shutdown_send failed");
1715 : }
1716 50 : tevent_req_set_callback(subreq,
1717 : smbd_server_connection_terminate_done,
1718 : xconn);
1719 50 : return;
1720 : }
1721 :
1722 : /*
1723 : * The last connection was disconnected
1724 : */
1725 4981 : exit_server_cleanly(reason);
1726 : }
1727 :
1728 0 : void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
1729 : const char *reason,
1730 : const char *location)
1731 : {
1732 0 : size_t num_ok = 0;
1733 :
1734 0 : num_ok = smbXsrv_client_valid_connections(client);
1735 :
1736 0 : DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
1737 : client->global->remote_address, num_ok,
1738 : reason, location);
1739 :
1740 : /*
1741 : * Something bad happened we need to disconnect all connections.
1742 : */
1743 0 : exit_server_cleanly(reason);
1744 : }
1745 :
1746 0 : static bool dup_smb2_vec4(TALLOC_CTX *ctx,
1747 : struct iovec *outvec,
1748 : const struct iovec *srcvec)
1749 : {
1750 : const uint8_t *srctf;
1751 : size_t srctf_len;
1752 : const uint8_t *srchdr;
1753 : size_t srchdr_len;
1754 : const uint8_t *srcbody;
1755 : size_t srcbody_len;
1756 : const uint8_t *expected_srcbody;
1757 : const uint8_t *srcdyn;
1758 : size_t srcdyn_len;
1759 : const uint8_t *expected_srcdyn;
1760 : uint8_t *dsttf;
1761 : uint8_t *dsthdr;
1762 : uint8_t *dstbody;
1763 : uint8_t *dstdyn;
1764 :
1765 0 : srctf = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
1766 0 : srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
1767 0 : srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
1768 0 : srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
1769 0 : srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
1770 0 : srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
1771 0 : expected_srcbody = srchdr + SMB2_HDR_BODY;
1772 0 : srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
1773 0 : srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
1774 0 : expected_srcdyn = srcbody + 8;
1775 :
1776 0 : if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
1777 0 : return false;
1778 : }
1779 :
1780 0 : if (srchdr_len != SMB2_HDR_BODY) {
1781 0 : return false;
1782 : }
1783 :
1784 0 : if (srctf_len == SMB2_TF_HDR_SIZE) {
1785 0 : dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
1786 0 : if (dsttf == NULL) {
1787 0 : return false;
1788 : }
1789 : } else {
1790 0 : dsttf = NULL;
1791 : }
1792 0 : outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
1793 0 : outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
1794 :
1795 : /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
1796 : * be allocated with size OUTVEC_ALLOC_SIZE. */
1797 :
1798 0 : dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
1799 0 : if (dsthdr == NULL) {
1800 0 : return false;
1801 : }
1802 0 : outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
1803 0 : outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
1804 :
1805 : /*
1806 : * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
1807 : * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
1808 : * then duplicate this. Else use talloc_memdup().
1809 : */
1810 :
1811 0 : if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
1812 0 : dstbody = dsthdr + SMB2_HDR_BODY;
1813 : } else {
1814 0 : dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
1815 0 : if (dstbody == NULL) {
1816 0 : return false;
1817 : }
1818 : }
1819 0 : outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
1820 0 : outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
1821 :
1822 : /*
1823 : * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
1824 : * pointing to
1825 : * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
1826 : * then duplicate this. Else use talloc_memdup().
1827 : */
1828 :
1829 0 : if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
1830 0 : dstdyn = dsthdr + SMB2_HDR_BODY + 8;
1831 0 : } else if (srcdyn == NULL) {
1832 0 : dstdyn = NULL;
1833 : } else {
1834 0 : dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
1835 0 : if (dstdyn == NULL) {
1836 0 : return false;
1837 : }
1838 : }
1839 0 : outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
1840 0 : outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
1841 :
1842 0 : return true;
1843 : }
1844 :
1845 0 : static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
1846 : {
1847 0 : struct smbd_smb2_request *newreq = NULL;
1848 0 : struct iovec *outvec = NULL;
1849 0 : int count = req->out.vector_count;
1850 : int i;
1851 : bool ok;
1852 :
1853 0 : newreq = smbd_smb2_request_allocate(req->xconn);
1854 0 : if (!newreq) {
1855 0 : return NULL;
1856 : }
1857 :
1858 0 : newreq->sconn = req->sconn;
1859 0 : newreq->xconn = req->xconn;
1860 0 : newreq->session = req->session;
1861 0 : newreq->do_encryption = req->do_encryption;
1862 0 : newreq->do_signing = req->do_signing;
1863 0 : newreq->current_idx = req->current_idx;
1864 :
1865 0 : outvec = talloc_zero_array(newreq, struct iovec, count);
1866 0 : if (!outvec) {
1867 0 : TALLOC_FREE(newreq);
1868 0 : return NULL;
1869 : }
1870 0 : newreq->out.vector = outvec;
1871 0 : newreq->out.vector_count = count;
1872 :
1873 : /* Setup the outvec's identically to req. */
1874 0 : outvec[0].iov_base = newreq->out.nbt_hdr;
1875 0 : outvec[0].iov_len = 4;
1876 0 : memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
1877 :
1878 : /* Setup the vectors identically to the ones in req. */
1879 0 : for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
1880 0 : if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
1881 0 : break;
1882 : }
1883 : }
1884 :
1885 0 : if (i < count) {
1886 : /* Alloc failed. */
1887 0 : TALLOC_FREE(newreq);
1888 0 : return NULL;
1889 : }
1890 :
1891 0 : ok = smb2_setup_nbt_length(newreq->out.vector,
1892 : newreq->out.vector_count);
1893 0 : if (!ok) {
1894 0 : TALLOC_FREE(newreq);
1895 0 : return NULL;
1896 : }
1897 :
1898 0 : return newreq;
1899 : }
1900 :
1901 0 : static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
1902 : {
1903 0 : struct smbXsrv_connection *xconn = req->xconn;
1904 0 : int first_idx = 1;
1905 0 : struct iovec *firsttf = NULL;
1906 0 : struct iovec *outhdr_v = NULL;
1907 0 : uint8_t *outhdr = NULL;
1908 0 : struct smbd_smb2_request *nreq = NULL;
1909 : NTSTATUS status;
1910 : bool ok;
1911 :
1912 : /* Create a new smb2 request we'll use
1913 : for the interim return. */
1914 0 : nreq = dup_smb2_req(req);
1915 0 : if (!nreq) {
1916 0 : return NT_STATUS_NO_MEMORY;
1917 : }
1918 :
1919 : /* Lose the last X out vectors. They're the
1920 : ones we'll be using for the async reply. */
1921 0 : nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
1922 :
1923 0 : ok = smb2_setup_nbt_length(nreq->out.vector,
1924 : nreq->out.vector_count);
1925 0 : if (!ok) {
1926 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
1927 : }
1928 :
1929 : /* Step back to the previous reply. */
1930 0 : nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
1931 0 : firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
1932 0 : outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
1933 0 : outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
1934 : /* And end the chain. */
1935 0 : SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
1936 :
1937 : /* Calculate outgoing credits */
1938 0 : smb2_calculate_credits(req, nreq);
1939 :
1940 0 : if (DEBUGLEVEL >= 10) {
1941 0 : dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
1942 0 : (unsigned int)nreq->current_idx );
1943 0 : dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
1944 0 : (unsigned int)nreq->out.vector_count );
1945 0 : print_req_vectors(nreq);
1946 : }
1947 :
1948 : /*
1949 : * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
1950 : * we need to sign/encrypt here with the last/first key we remembered
1951 : */
1952 0 : if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
1953 0 : status = smb2_signing_encrypt_pdu(req->first_enc_key,
1954 : firsttf,
1955 0 : nreq->out.vector_count - first_idx);
1956 0 : if (!NT_STATUS_IS_OK(status)) {
1957 0 : return status;
1958 : }
1959 0 : } else if (smb2_signing_key_valid(req->last_sign_key)) {
1960 0 : status = smb2_signing_sign_pdu(req->last_sign_key,
1961 : outhdr_v,
1962 : SMBD_SMB2_NUM_IOV_PER_REQ - 1);
1963 0 : if (!NT_STATUS_IS_OK(status)) {
1964 0 : return status;
1965 : }
1966 : }
1967 :
1968 0 : nreq->queue_entry.mem_ctx = nreq;
1969 0 : nreq->queue_entry.vector = nreq->out.vector;
1970 0 : nreq->queue_entry.count = nreq->out.vector_count;
1971 0 : DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
1972 0 : xconn->smb2.send_queue_len++;
1973 :
1974 0 : status = smbd_smb2_flush_send_queue(xconn);
1975 0 : if (!NT_STATUS_IS_OK(status)) {
1976 0 : return status;
1977 : }
1978 :
1979 0 : return NT_STATUS_OK;
1980 : }
1981 :
1982 : struct smbd_smb2_request_pending_state {
1983 : struct smbd_smb2_send_queue queue_entry;
1984 : uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
1985 : struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
1986 : };
1987 :
1988 : static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
1989 : struct tevent_timer *te,
1990 : struct timeval current_time,
1991 : void *private_data);
1992 :
1993 150927 : NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
1994 : struct tevent_req *subreq,
1995 : uint32_t defer_time)
1996 : {
1997 : NTSTATUS status;
1998 : struct timeval defer_endtime;
1999 150927 : uint8_t *outhdr = NULL;
2000 : uint32_t flags;
2001 :
2002 150927 : if (!tevent_req_is_in_progress(subreq)) {
2003 : /*
2004 : * This is a performance optimization,
2005 : * it avoids one tevent_loop iteration,
2006 : * which means we avoid one
2007 : * talloc_stackframe_pool/talloc_free pair.
2008 : */
2009 51486 : tevent_req_notify_callback(subreq);
2010 49058 : return NT_STATUS_OK;
2011 : }
2012 :
2013 99441 : req->subreq = subreq;
2014 99441 : subreq = NULL;
2015 :
2016 99441 : if (req->async_te) {
2017 : /* We're already async. */
2018 0 : return NT_STATUS_OK;
2019 : }
2020 :
2021 99441 : outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2022 99441 : flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2023 99441 : if (flags & SMB2_HDR_FLAG_ASYNC) {
2024 : /* We're already async. */
2025 0 : return NT_STATUS_OK;
2026 : }
2027 :
2028 99441 : if (req->async_internal || defer_time == 0) {
2029 : /*
2030 : * An SMB2 request implementation wants to handle the request
2031 : * asynchronously "internally" while keeping synchronous
2032 : * behaviour for the SMB2 request. This means we don't send an
2033 : * interim response and we can allow processing of compound SMB2
2034 : * requests (cf the subsequent check) for all cases.
2035 : */
2036 9162 : return NT_STATUS_OK;
2037 : }
2038 :
2039 90279 : if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
2040 : /*
2041 : * We're trying to go async in a compound request
2042 : * chain. This is only allowed for opens that cause an
2043 : * oplock break or for the last operation in the
2044 : * chain, otherwise it is not allowed. See
2045 : * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
2046 : */
2047 0 : const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2048 :
2049 0 : if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
2050 : /*
2051 : * Cancel the outstanding request.
2052 : */
2053 0 : bool ok = tevent_req_cancel(req->subreq);
2054 0 : if (ok) {
2055 0 : return NT_STATUS_OK;
2056 : }
2057 0 : TALLOC_FREE(req->subreq);
2058 0 : return smbd_smb2_request_error(req,
2059 : NT_STATUS_INTERNAL_ERROR);
2060 : }
2061 : }
2062 :
2063 90279 : if (DEBUGLEVEL >= 10) {
2064 0 : dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
2065 0 : (unsigned int)req->current_idx );
2066 0 : print_req_vectors(req);
2067 : }
2068 :
2069 90279 : if (req->current_idx > 1) {
2070 : /*
2071 : * We're going async in a compound
2072 : * chain after the first request has
2073 : * already been processed. Send an
2074 : * interim response containing the
2075 : * set of replies already generated.
2076 : */
2077 0 : int idx = req->current_idx;
2078 :
2079 0 : status = smb2_send_async_interim_response(req);
2080 0 : if (!NT_STATUS_IS_OK(status)) {
2081 0 : return status;
2082 : }
2083 0 : TALLOC_FREE(req->first_enc_key);
2084 :
2085 0 : req->current_idx = 1;
2086 :
2087 : /*
2088 : * Re-arrange the in.vectors to remove what
2089 : * we just sent.
2090 : */
2091 0 : memmove(&req->in.vector[1],
2092 0 : &req->in.vector[idx],
2093 0 : sizeof(req->in.vector[0])*(req->in.vector_count - idx));
2094 0 : req->in.vector_count = 1 + (req->in.vector_count - idx);
2095 :
2096 : /* Re-arrange the out.vectors to match. */
2097 0 : memmove(&req->out.vector[1],
2098 0 : &req->out.vector[idx],
2099 0 : sizeof(req->out.vector[0])*(req->out.vector_count - idx));
2100 0 : req->out.vector_count = 1 + (req->out.vector_count - idx);
2101 :
2102 0 : if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
2103 : /*
2104 : * We only have one remaining request as
2105 : * we've processed everything else.
2106 : * This is no longer a compound request.
2107 : */
2108 0 : req->compound_related = false;
2109 0 : outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2110 0 : flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
2111 0 : SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
2112 : }
2113 : }
2114 90279 : TALLOC_FREE(req->last_sign_key);
2115 :
2116 : /*
2117 : * smbd_smb2_request_pending_timer() just send a packet
2118 : * to the client and doesn't need any impersonation.
2119 : * So we use req->xconn->client->raw_ev_ctx instead
2120 : * of req->ev_ctx here.
2121 : */
2122 90279 : defer_endtime = timeval_current_ofs_usec(defer_time);
2123 90279 : req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
2124 : req, defer_endtime,
2125 : smbd_smb2_request_pending_timer,
2126 : req);
2127 90279 : if (req->async_te == NULL) {
2128 0 : return NT_STATUS_NO_MEMORY;
2129 : }
2130 :
2131 90279 : return NT_STATUS_OK;
2132 : }
2133 :
2134 : static
2135 254793 : struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
2136 : struct smbXsrv_connection *xconn,
2137 : bool *_has_channel)
2138 : {
2139 254793 : struct smbXsrv_channel_global0 *c = NULL;
2140 : NTSTATUS status;
2141 254793 : struct smb2_signing_key *key = NULL;
2142 254793 : bool has_channel = false;
2143 :
2144 254793 : status = smbXsrv_session_find_channel(session, xconn, &c);
2145 254793 : if (NT_STATUS_IS_OK(status)) {
2146 254277 : key = c->signing_key;
2147 254277 : has_channel = true;
2148 : }
2149 :
2150 254793 : if (!smb2_signing_key_valid(key)) {
2151 520 : key = session->global->signing_key;
2152 520 : has_channel = false;
2153 : }
2154 :
2155 254793 : if (_has_channel != NULL) {
2156 125203 : *_has_channel = has_channel;
2157 : }
2158 :
2159 254793 : return key;
2160 : }
2161 :
2162 634 : static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
2163 : uint64_t *new_nonce_high,
2164 : uint64_t *new_nonce_low)
2165 : {
2166 : uint64_t nonce_high;
2167 : uint64_t nonce_low;
2168 :
2169 634 : session->nonce_low += 1;
2170 634 : if (session->nonce_low == 0) {
2171 0 : session->nonce_low += 1;
2172 0 : session->nonce_high += 1;
2173 : }
2174 :
2175 : /*
2176 : * CCM and GCM algorithms must never have their
2177 : * nonce wrap, or the security of the whole
2178 : * communication and the keys is destroyed.
2179 : * We must drop the connection once we have
2180 : * transfered too much data.
2181 : *
2182 : * NOTE: We assume nonces greater than 8 bytes.
2183 : */
2184 634 : if (session->nonce_high >= session->nonce_high_max) {
2185 0 : return NT_STATUS_ENCRYPTION_FAILED;
2186 : }
2187 :
2188 634 : nonce_high = session->nonce_high_random;
2189 634 : nonce_high += session->nonce_high;
2190 634 : nonce_low = session->nonce_low;
2191 :
2192 634 : *new_nonce_high = nonce_high;
2193 634 : *new_nonce_low = nonce_low;
2194 634 : return NT_STATUS_OK;
2195 : }
2196 :
2197 20071 : static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
2198 : struct tevent_timer *te,
2199 : struct timeval current_time,
2200 : void *private_data)
2201 : {
2202 : struct smbd_smb2_request *req =
2203 20071 : talloc_get_type_abort(private_data,
2204 : struct smbd_smb2_request);
2205 20071 : struct smbXsrv_connection *xconn = req->xconn;
2206 20071 : struct smbd_smb2_request_pending_state *state = NULL;
2207 20071 : uint8_t *outhdr = NULL;
2208 20071 : const uint8_t *inhdr = NULL;
2209 20071 : uint8_t *tf = NULL;
2210 20071 : uint8_t *hdr = NULL;
2211 20071 : uint8_t *body = NULL;
2212 20071 : uint8_t *dyn = NULL;
2213 20071 : uint32_t flags = 0;
2214 20071 : uint64_t message_id = 0;
2215 20071 : uint64_t async_id = 0;
2216 : NTSTATUS status;
2217 : bool ok;
2218 :
2219 20071 : TALLOC_FREE(req->async_te);
2220 :
2221 : /* Ensure our final reply matches the interim one. */
2222 20071 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2223 20071 : outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
2224 20071 : flags = IVAL(outhdr, SMB2_HDR_FLAGS);
2225 20071 : message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2226 :
2227 20071 : async_id = message_id; /* keep it simple for now... */
2228 :
2229 20071 : SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2230 20071 : SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
2231 :
2232 20071 : DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
2233 : "going async\n",
2234 : smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2235 : (unsigned long long)async_id ));
2236 :
2237 : /*
2238 : * What we send is identical to a smbd_smb2_request_error
2239 : * packet with an error status of STATUS_PENDING. Make use
2240 : * of this fact sometime when refactoring. JRA.
2241 : */
2242 :
2243 20071 : state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
2244 20071 : if (state == NULL) {
2245 0 : smbd_server_connection_terminate(xconn,
2246 : nt_errstr(NT_STATUS_NO_MEMORY));
2247 0 : return;
2248 : }
2249 :
2250 20071 : tf = state->buf + NBT_HDR_SIZE;
2251 :
2252 20071 : hdr = tf + SMB2_TF_HDR_SIZE;
2253 20071 : body = hdr + SMB2_HDR_BODY;
2254 20071 : dyn = body + 8;
2255 :
2256 20071 : if (req->do_encryption) {
2257 20 : uint64_t nonce_high = 0;
2258 20 : uint64_t nonce_low = 0;
2259 20 : uint64_t session_id = req->session->global->session_wire_id;
2260 :
2261 20 : status = smb2_get_new_nonce(req->session,
2262 : &nonce_high,
2263 : &nonce_low);
2264 20 : if (!NT_STATUS_IS_OK(status)) {
2265 0 : smbd_server_connection_terminate(xconn,
2266 : nt_errstr(status));
2267 0 : return;
2268 : }
2269 :
2270 20 : SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
2271 20 : SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
2272 20 : SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
2273 20 : SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
2274 : }
2275 :
2276 20071 : SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
2277 20071 : SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
2278 20071 : SSVAL(hdr, SMB2_HDR_EPOCH, 0);
2279 20071 : SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
2280 20071 : SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
2281 :
2282 : /*
2283 : * The STATUS_PENDING response has SMB2_HDR_FLAG_SIGNED
2284 : * clearedm, but echoes the signature field.
2285 : */
2286 20071 : flags &= ~SMB2_HDR_FLAG_SIGNED;
2287 20071 : SIVAL(hdr, SMB2_HDR_FLAGS, flags);
2288 20071 : SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
2289 20071 : SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
2290 20071 : SBVAL(hdr, SMB2_HDR_PID, async_id);
2291 20071 : SBVAL(hdr, SMB2_HDR_SESSION_ID,
2292 : BVAL(outhdr, SMB2_HDR_SESSION_ID));
2293 20071 : memcpy(hdr+SMB2_HDR_SIGNATURE,
2294 20071 : outhdr+SMB2_HDR_SIGNATURE, 16);
2295 :
2296 20071 : SSVAL(body, 0x00, 0x08 + 1);
2297 :
2298 20071 : SCVAL(body, 0x02, 0);
2299 20071 : SCVAL(body, 0x03, 0);
2300 20071 : SIVAL(body, 0x04, 0);
2301 : /* Match W2K8R2... */
2302 20071 : SCVAL(dyn, 0x00, 0x21);
2303 :
2304 20071 : state->vector[0].iov_base = (void *)state->buf;
2305 20071 : state->vector[0].iov_len = NBT_HDR_SIZE;
2306 :
2307 20071 : if (req->do_encryption) {
2308 20 : state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = tf;
2309 20 : state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len =
2310 : SMB2_TF_HDR_SIZE;
2311 : } else {
2312 20051 : state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base = NULL;
2313 20051 : state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len = 0;
2314 : }
2315 :
2316 20071 : state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base = hdr;
2317 20071 : state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
2318 :
2319 20071 : state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
2320 20071 : state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len = 8;
2321 :
2322 20071 : state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
2323 20071 : state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
2324 :
2325 20071 : ok = smb2_setup_nbt_length(state->vector,
2326 : 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
2327 20071 : if (!ok) {
2328 0 : smbd_server_connection_terminate(
2329 : xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
2330 0 : return;
2331 : }
2332 :
2333 : /* Ensure we correctly go through crediting. Grant
2334 : the credits now, and zero credits on the final
2335 : response. */
2336 20071 : smb2_set_operation_credit(req->xconn,
2337 20071 : SMBD_SMB2_IN_HDR_IOV(req),
2338 : &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
2339 :
2340 : /*
2341 : * We add SMB2_HDR_FLAG_ASYNC after smb2_set_operation_credit()
2342 : * as it reacts on it
2343 : */
2344 20071 : SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
2345 :
2346 20071 : if (DEBUGLVL(10)) {
2347 : int i;
2348 :
2349 0 : for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
2350 0 : dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
2351 : (unsigned int)i,
2352 : (unsigned int)ARRAY_SIZE(state->vector),
2353 0 : (unsigned int)state->vector[i].iov_len);
2354 : }
2355 : }
2356 :
2357 20071 : if (req->do_encryption) {
2358 20 : struct smbXsrv_session *x = req->session;
2359 20 : struct smb2_signing_key *encryption_key = x->global->encryption_key;
2360 :
2361 20 : status = smb2_signing_encrypt_pdu(encryption_key,
2362 : &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
2363 : SMBD_SMB2_NUM_IOV_PER_REQ);
2364 20 : if (!NT_STATUS_IS_OK(status)) {
2365 0 : smbd_server_connection_terminate(xconn,
2366 : nt_errstr(status));
2367 0 : return;
2368 : }
2369 : }
2370 :
2371 20071 : state->queue_entry.mem_ctx = state;
2372 20071 : state->queue_entry.vector = state->vector;
2373 20071 : state->queue_entry.count = ARRAY_SIZE(state->vector);
2374 20071 : DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
2375 20071 : xconn->smb2.send_queue_len++;
2376 :
2377 20071 : status = smbd_smb2_flush_send_queue(xconn);
2378 20071 : if (!NT_STATUS_IS_OK(status)) {
2379 0 : smbd_server_connection_terminate(xconn,
2380 : nt_errstr(status));
2381 0 : return;
2382 : }
2383 : }
2384 :
2385 18 : static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
2386 : {
2387 18 : struct smbXsrv_connection *xconn = req->xconn;
2388 : struct smbd_smb2_request *cur;
2389 : const uint8_t *inhdr;
2390 : uint32_t flags;
2391 : uint64_t search_message_id;
2392 : uint64_t search_async_id;
2393 : uint64_t found_id;
2394 :
2395 18 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2396 :
2397 18 : flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2398 18 : search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2399 18 : search_async_id = BVAL(inhdr, SMB2_HDR_PID);
2400 :
2401 : /*
2402 : * We don't need the request anymore cancel requests never
2403 : * have a response.
2404 : *
2405 : * We defer the TALLOC_FREE(req) to the caller.
2406 : */
2407 18 : DLIST_REMOVE(xconn->smb2.requests, req);
2408 :
2409 18 : for (cur = xconn->smb2.requests; cur; cur = cur->next) {
2410 : const uint8_t *outhdr;
2411 : uint64_t message_id;
2412 : uint64_t async_id;
2413 :
2414 18 : if (cur->session != req->session) {
2415 0 : continue;
2416 : }
2417 :
2418 18 : if (cur->compound_related) {
2419 : /*
2420 : * Never cancel anything in a compound request.
2421 : * Way too hard to deal with the result.
2422 : */
2423 0 : continue;
2424 : }
2425 :
2426 18 : outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
2427 :
2428 18 : message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
2429 18 : async_id = BVAL(outhdr, SMB2_HDR_PID);
2430 :
2431 18 : if (flags & SMB2_HDR_FLAG_ASYNC) {
2432 18 : if (search_async_id == async_id) {
2433 18 : found_id = async_id;
2434 18 : break;
2435 : }
2436 : } else {
2437 0 : if (search_message_id == message_id) {
2438 0 : found_id = message_id;
2439 0 : break;
2440 : }
2441 : }
2442 : }
2443 :
2444 18 : if (cur && cur->subreq) {
2445 18 : inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
2446 18 : DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
2447 : "cancel opcode[%s] mid %llu\n",
2448 : smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
2449 : (unsigned long long)found_id ));
2450 18 : tevent_req_cancel(cur->subreq);
2451 : }
2452 :
2453 18 : return NT_STATUS_OK;
2454 : }
2455 :
2456 : /*************************************************************
2457 : Ensure an incoming tid is a valid one for us to access.
2458 : Change to the associated uid credentials and chdir to the
2459 : valid tid directory.
2460 : *************************************************************/
2461 :
2462 136294 : static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
2463 : {
2464 : const uint8_t *inhdr;
2465 : uint32_t in_flags;
2466 : uint32_t in_tid;
2467 : struct smbXsrv_tcon *tcon;
2468 : NTSTATUS status;
2469 136294 : NTTIME now = timeval_to_nttime(&req->request_time);
2470 :
2471 136294 : req->tcon = NULL;
2472 :
2473 136294 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2474 :
2475 136294 : in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2476 136294 : in_tid = IVAL(inhdr, SMB2_HDR_TID);
2477 :
2478 136294 : if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2479 0 : in_tid = req->last_tid;
2480 : }
2481 :
2482 136294 : req->last_tid = 0;
2483 :
2484 136294 : status = smb2srv_tcon_lookup(req->session,
2485 : in_tid, now, &tcon);
2486 136294 : if (!NT_STATUS_IS_OK(status)) {
2487 14 : return status;
2488 : }
2489 :
2490 136280 : if (!change_to_user_and_service(
2491 136280 : tcon->compat,
2492 136280 : req->session->global->session_wire_id))
2493 : {
2494 24 : return NT_STATUS_ACCESS_DENIED;
2495 : }
2496 :
2497 136256 : req->tcon = tcon;
2498 136256 : req->last_tid = in_tid;
2499 :
2500 136256 : return NT_STATUS_OK;
2501 : }
2502 :
2503 : /*************************************************************
2504 : Ensure an incoming session_id is a valid one for us to access.
2505 : *************************************************************/
2506 :
2507 159518 : static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
2508 : {
2509 : const uint8_t *inhdr;
2510 : uint32_t in_flags;
2511 : uint16_t in_opcode;
2512 : uint64_t in_session_id;
2513 159518 : struct smbXsrv_session *session = NULL;
2514 : struct auth_session_info *session_info;
2515 : NTSTATUS status;
2516 159518 : NTTIME now = timeval_to_nttime(&req->request_time);
2517 :
2518 159518 : req->session = NULL;
2519 159518 : req->tcon = NULL;
2520 :
2521 159518 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2522 :
2523 159518 : in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2524 159518 : in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2525 159518 : in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
2526 :
2527 159518 : if (in_flags & SMB2_HDR_FLAG_CHAINED) {
2528 0 : in_session_id = req->last_session_id;
2529 : }
2530 :
2531 159518 : req->last_session_id = 0;
2532 :
2533 : /* look an existing session up */
2534 159518 : switch (in_opcode) {
2535 6767 : case SMB2_OP_SESSSETUP:
2536 : /*
2537 : * For a session bind request, we don't have the
2538 : * channel set up at this point yet, so we defer
2539 : * the verification that the connection belongs
2540 : * to the session to the session setup code, which
2541 : * can look at the session binding flags.
2542 : */
2543 6767 : status = smb2srv_session_lookup_client(req->xconn->client,
2544 : in_session_id, now,
2545 : &session);
2546 6767 : break;
2547 152751 : default:
2548 152751 : status = smb2srv_session_lookup_conn(req->xconn,
2549 : in_session_id, now,
2550 : &session);
2551 152751 : break;
2552 : }
2553 159518 : if (session) {
2554 146013 : req->session = session;
2555 146013 : req->last_session_id = in_session_id;
2556 : }
2557 159518 : if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
2558 13505 : switch (in_opcode) {
2559 5062 : case SMB2_OP_SESSSETUP:
2560 5062 : status = smb2srv_session_lookup_global(req->xconn->client,
2561 : in_session_id,
2562 : req,
2563 : &session);
2564 5062 : if (NT_STATUS_IS_OK(status)) {
2565 : /*
2566 : * We fallback to a session of
2567 : * another process in order to
2568 : * get the signing correct.
2569 : *
2570 : * We don't set req->last_session_id here.
2571 : */
2572 148 : req->session = session;
2573 : }
2574 5062 : break;
2575 8443 : default:
2576 8443 : break;
2577 : }
2578 : }
2579 159518 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
2580 106 : switch (in_opcode) {
2581 12 : case SMB2_OP_SESSSETUP:
2582 12 : status = NT_STATUS_OK;
2583 12 : break;
2584 28 : case SMB2_OP_LOGOFF:
2585 : case SMB2_OP_CLOSE:
2586 : case SMB2_OP_LOCK:
2587 : case SMB2_OP_CANCEL:
2588 : case SMB2_OP_KEEPALIVE:
2589 : /*
2590 : * [MS-SMB2] 3.3.5.2.9 Verifying the Session
2591 : * specifies that LOGOFF, CLOSE and (UN)LOCK
2592 : * should always be processed even on expired sessions.
2593 : *
2594 : * Also see the logic in
2595 : * smbd_smb2_request_process_lock().
2596 : *
2597 : * The smb2.session.expire2 test shows that
2598 : * CANCEL and KEEPALIVE/ECHO should also
2599 : * be processed.
2600 : */
2601 28 : status = NT_STATUS_OK;
2602 28 : break;
2603 66 : default:
2604 66 : break;
2605 : }
2606 : }
2607 159518 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2608 1505 : switch (in_opcode) {
2609 0 : case SMB2_OP_TCON:
2610 : case SMB2_OP_CREATE:
2611 : case SMB2_OP_GETINFO:
2612 : case SMB2_OP_SETINFO:
2613 0 : return NT_STATUS_INVALID_HANDLE;
2614 1505 : default:
2615 : /*
2616 : * Notice the check for
2617 : * (session_info == NULL)
2618 : * below.
2619 : */
2620 1505 : status = NT_STATUS_OK;
2621 1505 : break;
2622 : }
2623 : }
2624 159518 : if (!NT_STATUS_IS_OK(status)) {
2625 13423 : return status;
2626 : }
2627 :
2628 146095 : session_info = session->global->auth_session_info;
2629 146095 : if (session_info == NULL) {
2630 1495 : return NT_STATUS_INVALID_HANDLE;
2631 : }
2632 :
2633 144600 : return NT_STATUS_OK;
2634 : }
2635 :
2636 101298 : NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
2637 : uint32_t data_length)
2638 : {
2639 101298 : struct smbXsrv_connection *xconn = req->xconn;
2640 : uint16_t needed_charge;
2641 101298 : uint16_t credit_charge = 1;
2642 : const uint8_t *inhdr;
2643 :
2644 101298 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2645 :
2646 101298 : if (xconn->smb2.credits.multicredit) {
2647 100921 : credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
2648 100921 : credit_charge = MAX(credit_charge, 1);
2649 : }
2650 :
2651 101298 : needed_charge = (data_length - 1)/ 65536 + 1;
2652 :
2653 101298 : DBGC_DEBUG(DBGC_SMB2_CREDITS,
2654 : "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
2655 : (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
2656 : credit_charge, needed_charge);
2657 :
2658 101298 : if (needed_charge > credit_charge) {
2659 0 : DBGC_WARNING(DBGC_SMB2_CREDITS,
2660 : "CreditCharge too low, given %d, needed %d\n",
2661 : credit_charge, needed_charge);
2662 0 : return NT_STATUS_INVALID_PARAMETER;
2663 : }
2664 :
2665 101298 : return NT_STATUS_OK;
2666 : }
2667 :
2668 159360 : NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
2669 : size_t expected_body_size)
2670 : {
2671 : struct iovec *inhdr_v;
2672 : const uint8_t *inhdr;
2673 : uint16_t opcode;
2674 : const uint8_t *inbody;
2675 : size_t body_size;
2676 159360 : size_t min_dyn_size = expected_body_size & 0x00000001;
2677 159360 : int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
2678 :
2679 : /*
2680 : * The following should be checked already.
2681 : */
2682 159360 : if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
2683 0 : return NT_STATUS_INTERNAL_ERROR;
2684 : }
2685 159360 : if (req->current_idx > max_idx) {
2686 0 : return NT_STATUS_INTERNAL_ERROR;
2687 : }
2688 :
2689 159360 : inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
2690 159360 : if (inhdr_v->iov_len != SMB2_HDR_BODY) {
2691 0 : return NT_STATUS_INTERNAL_ERROR;
2692 : }
2693 159360 : if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
2694 0 : return NT_STATUS_INTERNAL_ERROR;
2695 : }
2696 :
2697 159360 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2698 159360 : opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2699 :
2700 159360 : switch (opcode) {
2701 89531 : case SMB2_OP_IOCTL:
2702 : case SMB2_OP_GETINFO:
2703 : case SMB2_OP_WRITE:
2704 89531 : min_dyn_size = 0;
2705 89531 : break;
2706 : }
2707 :
2708 : /*
2709 : * Now check the expected body size,
2710 : * where the last byte might be in the
2711 : * dynamic section..
2712 : */
2713 159360 : if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
2714 0 : return NT_STATUS_INVALID_PARAMETER;
2715 : }
2716 159360 : if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
2717 0 : return NT_STATUS_INVALID_PARAMETER;
2718 : }
2719 :
2720 159360 : inbody = SMBD_SMB2_IN_BODY_PTR(req);
2721 :
2722 159360 : body_size = SVAL(inbody, 0x00);
2723 159360 : if (body_size != expected_body_size) {
2724 0 : return NT_STATUS_INVALID_PARAMETER;
2725 : }
2726 :
2727 159360 : return NT_STATUS_OK;
2728 : }
2729 :
2730 0 : bool smbXsrv_is_encrypted(uint8_t encryption_flags)
2731 : {
2732 0 : return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
2733 0 : &&
2734 0 : (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
2735 : SMBXSRV_ENCRYPTION_DESIRED |
2736 : SMBXSRV_ENCRYPTION_REQUIRED)));
2737 : }
2738 :
2739 0 : bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
2740 : {
2741 0 : return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
2742 0 : (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
2743 : }
2744 :
2745 : /* Set a flag if not already set, return true if set */
2746 564470 : bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
2747 : {
2748 564470 : if ((flag == 0) || (*flags & flag)) {
2749 542281 : return false;
2750 : }
2751 :
2752 22189 : *flags |= flag;
2753 22189 : return true;
2754 : }
2755 :
2756 : /*
2757 : * Update encryption state tracking flags, this can be used to
2758 : * determine whether whether the session or tcon is "encrypted".
2759 : */
2760 146045 : static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
2761 : uint16_t opcode,
2762 : bool *update_session_globalp,
2763 : bool *update_tcon_globalp)
2764 : {
2765 : /* Default: assume unecrypted and unsigned */
2766 146045 : struct smbXsrv_session *session = req->session;
2767 146045 : struct smbXsrv_tcon *tcon = req->tcon;
2768 146045 : uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
2769 146045 : uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
2770 146045 : bool update_session = false;
2771 146045 : bool update_tcon = false;
2772 :
2773 146045 : if (session->table == NULL) {
2774 : /*
2775 : * sessions from smb2srv_session_lookup_global()
2776 : * have NT_STATUS_BAD_LOGON_SESSION_STATE
2777 : * and session->table == NULL.
2778 : *
2779 : * They only used to give the correct error
2780 : * status, we should not update any state.
2781 : */
2782 182 : goto out;
2783 : }
2784 :
2785 145863 : if (req->was_encrypted && req->do_encryption) {
2786 594 : encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
2787 594 : sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2788 : } else {
2789 : /* Unencrypted packet, can be signed */
2790 145269 : if (req->do_signing) {
2791 124995 : sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
2792 : }
2793 : }
2794 :
2795 291726 : update_session |= smbXsrv_set_crypto_flag(
2796 145863 : &session->global->encryption_flags, encrypt_flag);
2797 291726 : update_session |= smbXsrv_set_crypto_flag(
2798 145863 : &session->global->signing_flags, sign_flag);
2799 :
2800 145863 : if (tcon) {
2801 272512 : update_tcon |= smbXsrv_set_crypto_flag(
2802 136256 : &tcon->global->encryption_flags, encrypt_flag);
2803 136256 : update_tcon |= smbXsrv_set_crypto_flag(
2804 136256 : &tcon->global->signing_flags, sign_flag);
2805 : }
2806 :
2807 9607 : out:
2808 146045 : *update_session_globalp = update_session;
2809 146045 : *update_tcon_globalp = update_tcon;
2810 146045 : return;
2811 : }
2812 :
2813 0 : bool smbXsrv_is_signed(uint8_t signing_flags)
2814 : {
2815 : /*
2816 : * Signing is always enabled, so unless we got an unsigned
2817 : * packet and at least one signed packet that was not
2818 : * encrypted, the session or tcon is "signed".
2819 : */
2820 0 : return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2821 0 : (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2822 : }
2823 :
2824 0 : bool smbXsrv_is_partially_signed(uint8_t signing_flags)
2825 : {
2826 0 : return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
2827 0 : (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
2828 : }
2829 :
2830 159378 : static NTSTATUS smbd_smb2_request_dispatch_update_counts(
2831 : struct smbd_smb2_request *req,
2832 : bool modify_call)
2833 : {
2834 159378 : struct smbXsrv_connection *xconn = req->xconn;
2835 : const uint8_t *inhdr;
2836 : uint16_t channel_sequence;
2837 159378 : uint8_t generation_wrap = 0;
2838 : uint32_t flags;
2839 : int cmp;
2840 : struct smbXsrv_open *op;
2841 159378 : bool update_open = false;
2842 159378 : NTSTATUS status = NT_STATUS_OK;
2843 :
2844 159378 : SMB_ASSERT(!req->request_counters_updated);
2845 :
2846 159378 : if (xconn->protocol < PROTOCOL_SMB3_00) {
2847 78550 : return NT_STATUS_OK;
2848 : }
2849 :
2850 80828 : if (req->compat_chain_fsp == NULL) {
2851 21053 : return NT_STATUS_OK;
2852 : }
2853 :
2854 59775 : op = req->compat_chain_fsp->op;
2855 59775 : if (op == NULL) {
2856 0 : return NT_STATUS_OK;
2857 : }
2858 :
2859 59775 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2860 59775 : flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2861 59775 : channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
2862 :
2863 59775 : cmp = channel_sequence - op->global->channel_sequence;
2864 59775 : if (cmp < 0) {
2865 : /*
2866 : * csn wrap. We need to watch out for long-running
2867 : * requests that are still sitting on a previously
2868 : * used csn. SMB2_OP_NOTIFY can take VERY long.
2869 : */
2870 0 : generation_wrap += 1;
2871 : }
2872 :
2873 59775 : if (abs(cmp) > INT16_MAX) {
2874 : /*
2875 : * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
2876 : *
2877 : * If the channel sequence number of the request and the one
2878 : * known to the server are not equal, the channel sequence
2879 : * number and outstanding request counts are only updated
2880 : * "... if the unsigned difference using 16-bit arithmetic
2881 : * between ChannelSequence and Open.ChannelSequence is less than
2882 : * or equal to 0x7FFF ...".
2883 : * Otherwise, an error is returned for the modifying
2884 : * calls write, set_info, and ioctl.
2885 : *
2886 : * There are currently two issues with the description:
2887 : *
2888 : * * For the other calls, the document seems to imply
2889 : * that processing continues without adapting the
2890 : * counters (if the sequence numbers are not equal).
2891 : *
2892 : * TODO: This needs clarification!
2893 : *
2894 : * * Also, the behaviour if the difference is larger
2895 : * than 0x7FFF is not clear. The document seems to
2896 : * imply that if such a difference is reached,
2897 : * the server starts to ignore the counters or
2898 : * in the case of the modifying calls, return errors.
2899 : *
2900 : * TODO: This needs clarification!
2901 : *
2902 : * At this point Samba tries to be a little more
2903 : * clever than the description in the MS-SMB2 document
2904 : * by heuristically detecting and properly treating
2905 : * a 16 bit overflow of the client-submitted sequence
2906 : * number:
2907 : *
2908 : * If the stored channel sequence number is more than
2909 : * 0x7FFF larger than the one from the request, then
2910 : * the client-provided sequence number has likely
2911 : * overflown. We treat this case as valid instead
2912 : * of as failure.
2913 : *
2914 : * The MS-SMB2 behaviour would be setting cmp = -1.
2915 : */
2916 0 : cmp *= -1;
2917 : }
2918 :
2919 59775 : if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
2920 0 : if (cmp == 0 && op->pre_request_count == 0) {
2921 0 : op->request_count += 1;
2922 0 : req->request_counters_updated = true;
2923 0 : } else if (cmp > 0 && op->pre_request_count == 0) {
2924 0 : op->pre_request_count += op->request_count;
2925 0 : op->request_count = 1;
2926 0 : op->global->channel_sequence = channel_sequence;
2927 0 : op->global->channel_generation += generation_wrap;
2928 0 : update_open = true;
2929 0 : req->request_counters_updated = true;
2930 0 : } else if (modify_call) {
2931 0 : return NT_STATUS_FILE_NOT_AVAILABLE;
2932 : }
2933 : } else {
2934 59775 : if (cmp == 0) {
2935 59775 : op->request_count += 1;
2936 59775 : req->request_counters_updated = true;
2937 0 : } else if (cmp > 0) {
2938 0 : op->pre_request_count += op->request_count;
2939 0 : op->request_count = 1;
2940 0 : op->global->channel_sequence = channel_sequence;
2941 0 : op->global->channel_generation += generation_wrap;
2942 0 : update_open = true;
2943 0 : req->request_counters_updated = true;
2944 0 : } else if (modify_call) {
2945 0 : return NT_STATUS_FILE_NOT_AVAILABLE;
2946 : }
2947 : }
2948 59775 : req->channel_generation = op->global->channel_generation;
2949 :
2950 59775 : if (update_open) {
2951 0 : status = smbXsrv_open_update(op);
2952 : }
2953 :
2954 59775 : return status;
2955 : }
2956 :
2957 159518 : NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
2958 : {
2959 159518 : struct smbXsrv_connection *xconn = req->xconn;
2960 159518 : const struct smbd_smb2_dispatch_table *call = NULL;
2961 159518 : const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
2962 : const uint8_t *inhdr;
2963 : uint16_t opcode;
2964 : uint32_t flags;
2965 : uint64_t mid;
2966 : NTSTATUS status;
2967 : NTSTATUS session_status;
2968 : uint32_t allowed_flags;
2969 : NTSTATUS return_value;
2970 159518 : struct smbXsrv_session *x = NULL;
2971 159518 : bool signing_required = false;
2972 159518 : bool encryption_desired = false;
2973 159518 : bool encryption_required = false;
2974 :
2975 159518 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
2976 :
2977 159518 : DO_PROFILE_INC(request);
2978 :
2979 159518 : SMB_ASSERT(!req->request_counters_updated);
2980 :
2981 : /* TODO: verify more things */
2982 :
2983 159518 : flags = IVAL(inhdr, SMB2_HDR_FLAGS);
2984 159518 : opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
2985 159518 : mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
2986 159518 : DBG_DEBUG("opcode[%s] mid = %"PRIu64"\n",
2987 : smb2_opcode_name(opcode),
2988 : mid);
2989 :
2990 159518 : if (xconn->protocol >= PROTOCOL_SMB2_02) {
2991 : /*
2992 : * once the protocol is negotiated
2993 : * SMB2_OP_NEGPROT is not allowed anymore
2994 : */
2995 151153 : if (opcode == SMB2_OP_NEGPROT) {
2996 : /* drop the connection */
2997 0 : return NT_STATUS_INVALID_PARAMETER;
2998 : }
2999 : } else {
3000 : /*
3001 : * if the protocol is not negotiated yet
3002 : * only SMB2_OP_NEGPROT is allowed.
3003 : */
3004 8365 : if (opcode != SMB2_OP_NEGPROT) {
3005 : /* drop the connection */
3006 0 : return NT_STATUS_INVALID_PARAMETER;
3007 : }
3008 : }
3009 :
3010 : /*
3011 : * Check if the client provided a valid session id.
3012 : *
3013 : * As some command don't require a valid session id
3014 : * we defer the check of the session_status
3015 : */
3016 159518 : session_status = smbd_smb2_request_check_session(req);
3017 159518 : x = req->session;
3018 159518 : if (x != NULL) {
3019 146161 : signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
3020 146161 : encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
3021 146161 : encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
3022 : }
3023 :
3024 159518 : req->async_internal = false;
3025 159518 : req->do_signing = false;
3026 159518 : if (opcode != SMB2_OP_SESSSETUP) {
3027 152751 : req->do_encryption = encryption_desired;
3028 : } else {
3029 6767 : req->do_encryption = false;
3030 : }
3031 159518 : req->was_encrypted = false;
3032 159518 : if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
3033 624 : const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
3034 624 : uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
3035 :
3036 624 : if (x != NULL && x->global->session_wire_id != tf_session_id) {
3037 0 : DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
3038 : "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
3039 : (unsigned long long)x->global->session_wire_id,
3040 : (unsigned long long)tf_session_id));
3041 : /*
3042 : * TODO: windows allows this...
3043 : * should we drop the connection?
3044 : *
3045 : * For now we just return ACCESS_DENIED
3046 : * (Windows clients never trigger this)
3047 : * and wait for an update of [MS-SMB2].
3048 : */
3049 0 : return smbd_smb2_request_error(req,
3050 : NT_STATUS_ACCESS_DENIED);
3051 : }
3052 :
3053 624 : req->was_encrypted = true;
3054 624 : req->do_encryption = true;
3055 : }
3056 :
3057 159518 : if (encryption_required && !req->was_encrypted) {
3058 0 : req->do_encryption = true;
3059 0 : return smbd_smb2_request_error(req,
3060 : NT_STATUS_ACCESS_DENIED);
3061 : }
3062 :
3063 159518 : call = smbd_smb2_call(opcode);
3064 159518 : if (call == NULL) {
3065 0 : return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3066 : }
3067 :
3068 159518 : allowed_flags = SMB2_HDR_FLAG_CHAINED |
3069 : SMB2_HDR_FLAG_SIGNED |
3070 : SMB2_HDR_FLAG_DFS;
3071 159518 : if (xconn->protocol >= PROTOCOL_SMB3_11) {
3072 80880 : allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3073 : }
3074 159518 : if (opcode == SMB2_OP_NEGPROT) {
3075 8365 : if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
3076 4833 : allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
3077 : }
3078 : }
3079 159518 : if (opcode == SMB2_OP_CANCEL) {
3080 18 : allowed_flags |= SMB2_HDR_FLAG_ASYNC;
3081 : }
3082 159518 : if (xconn->protocol >= PROTOCOL_SMB3_00) {
3083 80968 : allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
3084 : }
3085 159518 : if ((flags & ~allowed_flags) != 0) {
3086 0 : return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3087 : }
3088 :
3089 159518 : if (flags & SMB2_HDR_FLAG_CHAINED) {
3090 : /*
3091 : * This check is mostly for giving the correct error code
3092 : * for compounded requests.
3093 : */
3094 0 : if (!NT_STATUS_IS_OK(session_status)) {
3095 0 : return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3096 : }
3097 : } else {
3098 159518 : req->compat_chain_fsp = NULL;
3099 : }
3100 :
3101 159518 : if (req->was_encrypted) {
3102 624 : signing_required = false;
3103 158894 : } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
3104 125225 : struct smb2_signing_key *signing_key = NULL;
3105 125225 : bool has_channel = false;
3106 :
3107 125225 : if (x == NULL) {
3108 : /*
3109 : * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
3110 : * If the SMB2 header of the SMB2 NEGOTIATE
3111 : * request has the SMB2_FLAGS_SIGNED bit set in the
3112 : * Flags field, the server MUST fail the request
3113 : * with STATUS_INVALID_PARAMETER.
3114 : *
3115 : * Microsoft test tool checks this.
3116 : */
3117 :
3118 22 : if ((opcode == SMB2_OP_NEGPROT) &&
3119 0 : (flags & SMB2_HDR_FLAG_SIGNED)) {
3120 0 : status = NT_STATUS_INVALID_PARAMETER;
3121 : } else {
3122 22 : status = NT_STATUS_USER_SESSION_DELETED;
3123 : }
3124 70 : return smbd_smb2_request_error(req, status);
3125 : }
3126 :
3127 125203 : signing_key = smbd_smb2_signing_key(x, xconn, &has_channel);
3128 :
3129 : /*
3130 : * If we have a signing key, we should
3131 : * sign the response
3132 : */
3133 125203 : if (smb2_signing_key_valid(signing_key) && opcode != SMB2_OP_CANCEL) {
3134 125195 : req->do_signing = true;
3135 : }
3136 :
3137 125203 : status = smb2_signing_check_pdu(signing_key,
3138 125203 : SMBD_SMB2_IN_HDR_IOV(req),
3139 : SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3140 125203 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
3141 46 : opcode == SMB2_OP_SESSSETUP && !has_channel &&
3142 34 : NT_STATUS_IS_OK(session_status))
3143 : {
3144 34 : if (!NT_STATUS_EQUAL(x->status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
3145 34 : struct smbXsrv_session *session = NULL;
3146 : NTSTATUS error;
3147 :
3148 34 : error = smb2srv_session_lookup_global(req->xconn->client,
3149 34 : x->global->session_wire_id,
3150 : req,
3151 : &session);
3152 34 : if (!NT_STATUS_IS_OK(error)) {
3153 0 : return smbd_smb2_request_error(req, error);
3154 : }
3155 :
3156 : /*
3157 : * We fallback to a session of
3158 : * another process in order to
3159 : * get the signing correct.
3160 : *
3161 : * We don't set req->last_session_id here.
3162 : */
3163 34 : req->session = x = session;
3164 : }
3165 34 : goto skipped_signing;
3166 : }
3167 125169 : if (!NT_STATUS_IS_OK(status)) {
3168 12 : return smbd_smb2_request_error(req, status);
3169 : }
3170 :
3171 : /*
3172 : * Now that we know the request was correctly signed
3173 : * we have to sign the response too.
3174 : */
3175 125157 : if (opcode != SMB2_OP_CANCEL) {
3176 125149 : req->do_signing = true;
3177 : }
3178 :
3179 125157 : if (!NT_STATUS_IS_OK(session_status)) {
3180 36 : return smbd_smb2_request_error(req, session_status);
3181 : }
3182 : }
3183 :
3184 159414 : if (opcode == SMB2_OP_IOCTL) {
3185 : /*
3186 : * Some special IOCTL calls don't require
3187 : * file, tcon nor session.
3188 : *
3189 : * They typically don't do any real action
3190 : * on behalf of the client.
3191 : *
3192 : * They are mainly used to alter the behavior
3193 : * of the connection for testing. So we can
3194 : * run as root and skip all file, tcon and session
3195 : * checks below.
3196 : */
3197 : static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
3198 : _OP(SMB2_OP_IOCTL),
3199 : .as_root = true,
3200 : };
3201 81562 : const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3202 81562 : size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3203 : uint32_t in_ctl_code;
3204 81562 : size_t needed = 8;
3205 :
3206 81562 : if (needed > body_size) {
3207 0 : return smbd_smb2_request_error(req,
3208 : NT_STATUS_INVALID_PARAMETER);
3209 : }
3210 :
3211 81562 : in_ctl_code = IVAL(body, 0x04);
3212 : /*
3213 : * Only add trusted IOCTL codes here!
3214 : */
3215 81562 : switch (in_ctl_code) {
3216 0 : case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
3217 0 : call = &_root_ioctl_call;
3218 0 : break;
3219 2316 : case FSCTL_VALIDATE_NEGOTIATE_INFO:
3220 2316 : call = &_root_ioctl_call;
3221 2316 : break;
3222 0 : case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
3223 0 : call = &_root_ioctl_call;
3224 0 : break;
3225 : }
3226 : }
3227 :
3228 77852 : skipped_signing:
3229 :
3230 159448 : if (flags & SMB2_HDR_FLAG_CHAINED) {
3231 0 : req->compound_related = true;
3232 : }
3233 :
3234 159448 : if (call->need_session) {
3235 141934 : if (!NT_STATUS_IS_OK(session_status)) {
3236 30 : return smbd_smb2_request_error(req, session_status);
3237 : }
3238 : }
3239 :
3240 159418 : if (call->need_tcon) {
3241 136294 : SMB_ASSERT(call->need_session);
3242 :
3243 : /*
3244 : * This call needs to be run as user.
3245 : *
3246 : * smbd_smb2_request_check_tcon()
3247 : * calls change_to_user() on success.
3248 : * Which implies set_current_user_info()
3249 : * and chdir_current_service().
3250 : */
3251 136294 : status = smbd_smb2_request_check_tcon(req);
3252 136294 : if (!NT_STATUS_IS_OK(status)) {
3253 38 : return smbd_smb2_request_error(req, status);
3254 : }
3255 136256 : if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
3256 0 : encryption_desired = true;
3257 : }
3258 136256 : if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
3259 0 : encryption_required = true;
3260 : }
3261 136256 : if (encryption_required && !req->was_encrypted) {
3262 0 : req->do_encryption = true;
3263 0 : return smbd_smb2_request_error(req,
3264 : NT_STATUS_ACCESS_DENIED);
3265 136256 : } else if (encryption_desired) {
3266 0 : req->do_encryption = true;
3267 : }
3268 23124 : } else if (call->need_session) {
3269 5610 : struct auth_session_info *session_info = NULL;
3270 :
3271 : /*
3272 : * Unless we also have need_tcon (see above),
3273 : * we still need to call set_current_user_info().
3274 : */
3275 :
3276 5610 : session_info = req->session->global->auth_session_info;
3277 5610 : if (session_info == NULL) {
3278 0 : return NT_STATUS_INVALID_HANDLE;
3279 : }
3280 :
3281 5610 : set_current_user_info(session_info->unix_info->sanitized_username,
3282 5610 : session_info->unix_info->unix_name,
3283 5610 : session_info->info->domain_name);
3284 : }
3285 :
3286 159380 : if (req->session) {
3287 146045 : bool update_session_global = false;
3288 146045 : bool update_tcon_global = false;
3289 :
3290 146045 : smb2srv_update_crypto_flags(req, opcode,
3291 : &update_session_global,
3292 : &update_tcon_global);
3293 :
3294 146045 : if (update_session_global) {
3295 6301 : status = smbXsrv_session_update(x);
3296 6301 : if (!NT_STATUS_IS_OK(status)) {
3297 0 : return smbd_smb2_request_error(req, status);
3298 : }
3299 : }
3300 146045 : if (update_tcon_global) {
3301 5436 : status = smbXsrv_tcon_update(req->tcon);
3302 5436 : if (!NT_STATUS_IS_OK(status)) {
3303 0 : return smbd_smb2_request_error(req, status);
3304 : }
3305 : }
3306 : }
3307 :
3308 159380 : if (call->fileid_ofs != 0) {
3309 115382 : size_t needed = call->fileid_ofs + 16;
3310 115382 : const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
3311 115382 : size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
3312 : uint64_t file_id_persistent;
3313 : uint64_t file_id_volatile;
3314 : struct files_struct *fsp;
3315 :
3316 115382 : SMB_ASSERT(call->need_tcon);
3317 :
3318 115382 : if (needed > body_size) {
3319 0 : return smbd_smb2_request_error(req,
3320 : NT_STATUS_INVALID_PARAMETER);
3321 : }
3322 :
3323 115382 : file_id_persistent = BVAL(body, call->fileid_ofs + 0);
3324 115382 : file_id_volatile = BVAL(body, call->fileid_ofs + 8);
3325 :
3326 115382 : fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
3327 115382 : if (fsp == NULL) {
3328 1667 : if (req->compound_related &&
3329 0 : !NT_STATUS_IS_OK(req->compound_create_err))
3330 : {
3331 0 : return smbd_smb2_request_error(req,
3332 : req->compound_create_err);
3333 : }
3334 : /*
3335 : * smbd_smb2_request_process_ioctl()
3336 : * has more checks in order to return more
3337 : * detailed error codes...
3338 : */
3339 1667 : if (opcode != SMB2_OP_IOCTL) {
3340 2 : return smbd_smb2_request_error(req,
3341 : NT_STATUS_FILE_CLOSED);
3342 : }
3343 : } else {
3344 113715 : if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
3345 0 : return smbd_smb2_request_error(req,
3346 : NT_STATUS_ACCESS_DENIED);
3347 : }
3348 : }
3349 : }
3350 :
3351 159378 : status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
3352 159378 : if (!NT_STATUS_IS_OK(status)) {
3353 0 : return smbd_smb2_request_error(req, status);
3354 : }
3355 :
3356 159378 : if (call->as_root) {
3357 25522 : SMB_ASSERT(call->fileid_ofs == 0);
3358 : /* This call needs to be run as root */
3359 25522 : change_to_root_user();
3360 : } else {
3361 133856 : SMB_ASSERT(call->need_tcon);
3362 : }
3363 :
3364 : #define _INBYTES(_r) \
3365 : iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
3366 :
3367 159378 : switch (opcode) {
3368 8365 : case SMB2_OP_NEGPROT:
3369 8365 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
3370 : req->profile, _INBYTES(req));
3371 8365 : return_value = smbd_smb2_request_process_negprot(req);
3372 8365 : break;
3373 :
3374 6755 : case SMB2_OP_SESSSETUP:
3375 6755 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
3376 : req->profile, _INBYTES(req));
3377 6755 : return_value = smbd_smb2_request_process_sesssetup(req);
3378 6755 : break;
3379 :
3380 9 : case SMB2_OP_LOGOFF:
3381 9 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
3382 : req->profile, _INBYTES(req));
3383 9 : return_value = smbd_smb2_request_process_logoff(req);
3384 9 : break;
3385 :
3386 5601 : case SMB2_OP_TCON:
3387 5601 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
3388 : req->profile, _INBYTES(req));
3389 5601 : return_value = smbd_smb2_request_process_tcon(req);
3390 5601 : break;
3391 :
3392 2398 : case SMB2_OP_TDIS:
3393 2398 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
3394 : req->profile, _INBYTES(req));
3395 2398 : return_value = smbd_smb2_request_process_tdis(req);
3396 2398 : break;
3397 :
3398 18476 : case SMB2_OP_CREATE:
3399 18476 : if (req->subreq == NULL) {
3400 18476 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
3401 : req->profile, _INBYTES(req));
3402 : } else {
3403 0 : SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
3404 : }
3405 18476 : return_value = smbd_smb2_request_process_create(req);
3406 18476 : break;
3407 :
3408 16381 : case SMB2_OP_CLOSE:
3409 16381 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
3410 : req->profile, _INBYTES(req));
3411 16381 : return_value = smbd_smb2_request_process_close(req);
3412 13953 : break;
3413 :
3414 0 : case SMB2_OP_FLUSH:
3415 0 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
3416 : req->profile, _INBYTES(req));
3417 0 : return_value = smbd_smb2_request_process_flush(req);
3418 0 : break;
3419 :
3420 6388 : case SMB2_OP_READ:
3421 6388 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
3422 : req->profile, _INBYTES(req));
3423 6388 : return_value = smbd_smb2_request_process_read(req);
3424 6388 : break;
3425 :
3426 6324 : case SMB2_OP_WRITE:
3427 6324 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
3428 : req->profile, _INBYTES(req));
3429 6324 : return_value = smbd_smb2_request_process_write(req);
3430 6324 : break;
3431 :
3432 17 : case SMB2_OP_LOCK:
3433 17 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
3434 : req->profile, _INBYTES(req));
3435 17 : return_value = smbd_smb2_request_process_lock(req);
3436 17 : break;
3437 :
3438 81560 : case SMB2_OP_IOCTL:
3439 81560 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
3440 : req->profile, _INBYTES(req));
3441 81560 : return_value = smbd_smb2_request_process_ioctl(req);
3442 81560 : break;
3443 :
3444 18 : case SMB2_OP_CANCEL:
3445 18 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
3446 : req->profile, _INBYTES(req));
3447 18 : return_value = smbd_smb2_request_process_cancel(req);
3448 18 : SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
3449 :
3450 : /*
3451 : * We don't need the request anymore cancel requests never
3452 : * have a response.
3453 : *
3454 : * smbd_smb2_request_process_cancel() already called
3455 : * DLIST_REMOVE(xconn->smb2.requests, req);
3456 : */
3457 18 : TALLOC_FREE(req);
3458 :
3459 18 : break;
3460 :
3461 60 : case SMB2_OP_KEEPALIVE:
3462 60 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
3463 : req->profile, _INBYTES(req));
3464 60 : return_value = smbd_smb2_request_process_keepalive(req);
3465 60 : break;
3466 :
3467 4299 : case SMB2_OP_QUERY_DIRECTORY:
3468 4299 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
3469 : req->profile, _INBYTES(req));
3470 4299 : return_value = smbd_smb2_request_process_query_directory(req);
3471 4299 : break;
3472 :
3473 60 : case SMB2_OP_NOTIFY:
3474 60 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
3475 : req->profile, _INBYTES(req));
3476 60 : return_value = smbd_smb2_request_process_notify(req);
3477 60 : break;
3478 :
3479 1647 : case SMB2_OP_GETINFO:
3480 1647 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
3481 : req->profile, _INBYTES(req));
3482 1647 : return_value = smbd_smb2_request_process_getinfo(req);
3483 1647 : break;
3484 :
3485 1020 : case SMB2_OP_SETINFO:
3486 1020 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
3487 : req->profile, _INBYTES(req));
3488 1020 : return_value = smbd_smb2_request_process_setinfo(req);
3489 1020 : break;
3490 :
3491 0 : case SMB2_OP_BREAK:
3492 0 : SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
3493 : req->profile, _INBYTES(req));
3494 0 : return_value = smbd_smb2_request_process_break(req);
3495 0 : break;
3496 :
3497 0 : default:
3498 0 : return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
3499 0 : break;
3500 : }
3501 156950 : return return_value;
3502 : }
3503 :
3504 159450 : static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
3505 : {
3506 159450 : struct smbXsrv_connection *xconn = req->xconn;
3507 : const uint8_t *inhdr;
3508 : uint16_t channel_sequence;
3509 : struct smbXsrv_open *op;
3510 :
3511 159450 : if (!req->request_counters_updated) {
3512 99675 : return;
3513 : }
3514 :
3515 59775 : req->request_counters_updated = false;
3516 :
3517 59775 : if (xconn->protocol < PROTOCOL_SMB3_00) {
3518 0 : return;
3519 : }
3520 :
3521 59775 : if (req->compat_chain_fsp == NULL) {
3522 9152 : return;
3523 : }
3524 :
3525 50623 : op = req->compat_chain_fsp->op;
3526 50623 : if (op == NULL) {
3527 0 : return;
3528 : }
3529 :
3530 50623 : inhdr = SMBD_SMB2_IN_HDR_PTR(req);
3531 50623 : channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
3532 :
3533 50623 : if ((op->global->channel_sequence == channel_sequence) &&
3534 50623 : (op->global->channel_generation == req->channel_generation)) {
3535 50623 : SMB_ASSERT(op->request_count > 0);
3536 50623 : op->request_count -= 1;
3537 : } else {
3538 0 : SMB_ASSERT(op->pre_request_count > 0);
3539 0 : op->pre_request_count -= 1;
3540 : }
3541 : }
3542 :
3543 159450 : static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
3544 : {
3545 159450 : struct smbXsrv_connection *xconn = req->xconn;
3546 159450 : int first_idx = 1;
3547 159450 : struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
3548 159450 : struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
3549 159450 : struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
3550 : NTSTATUS status;
3551 : bool ok;
3552 :
3553 159450 : req->subreq = NULL;
3554 159450 : TALLOC_FREE(req->async_te);
3555 :
3556 : /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
3557 159450 : smbd_smb2_request_reply_update_counts(req);
3558 :
3559 159450 : if (req->do_encryption &&
3560 614 : (firsttf->iov_len == 0) &&
3561 614 : (!smb2_signing_key_valid(req->first_enc_key)) &&
3562 1228 : (req->session != NULL) &&
3563 614 : smb2_signing_key_valid(req->session->global->encryption_key))
3564 : {
3565 614 : struct smb2_signing_key *encryption_key =
3566 614 : req->session->global->encryption_key;
3567 : uint8_t *tf;
3568 614 : uint64_t session_id = req->session->global->session_wire_id;
3569 : uint64_t nonce_high;
3570 : uint64_t nonce_low;
3571 :
3572 614 : status = smb2_get_new_nonce(req->session,
3573 : &nonce_high,
3574 : &nonce_low);
3575 614 : if (!NT_STATUS_IS_OK(status)) {
3576 0 : return status;
3577 : }
3578 :
3579 : /*
3580 : * We need to place the SMB2_TRANSFORM header before the
3581 : * first SMB2 header
3582 : */
3583 :
3584 : /*
3585 : * we need to remember the encryption key
3586 : * and defer the signing/encryption until
3587 : * we are sure that we do not change
3588 : * the header again.
3589 : */
3590 614 : status = smb2_signing_key_copy(req,
3591 : encryption_key,
3592 : &req->first_enc_key);
3593 614 : if (!NT_STATUS_IS_OK(status)) {
3594 0 : return status;
3595 : }
3596 :
3597 614 : tf = talloc_zero_array(req, uint8_t,
3598 : SMB2_TF_HDR_SIZE);
3599 614 : if (tf == NULL) {
3600 0 : return NT_STATUS_NO_MEMORY;
3601 : }
3602 :
3603 614 : SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
3604 614 : SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
3605 614 : SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
3606 614 : SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
3607 :
3608 614 : firsttf->iov_base = (void *)tf;
3609 614 : firsttf->iov_len = SMB2_TF_HDR_SIZE;
3610 : }
3611 :
3612 159450 : if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
3613 0 : (smb2_signing_key_valid(req->last_sign_key)) &&
3614 0 : (firsttf->iov_len == 0))
3615 : {
3616 0 : int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
3617 0 : struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
3618 :
3619 : /*
3620 : * As we are sure the header of the last request in the
3621 : * compound chain will not change, we can to sign here
3622 : * with the last signing key we remembered.
3623 : */
3624 0 : status = smb2_signing_sign_pdu(req->last_sign_key,
3625 : lasthdr,
3626 : SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3627 0 : if (!NT_STATUS_IS_OK(status)) {
3628 0 : return status;
3629 : }
3630 : }
3631 159450 : TALLOC_FREE(req->last_sign_key);
3632 :
3633 159450 : SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
3634 : iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
3635 :
3636 159450 : req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
3637 :
3638 159450 : if (req->current_idx < req->out.vector_count) {
3639 : /*
3640 : * We must process the remaining compound
3641 : * SMB2 requests before any new incoming SMB2
3642 : * requests. This is because incoming SMB2
3643 : * requests may include a cancel for a
3644 : * compound request we haven't processed
3645 : * yet.
3646 : */
3647 0 : struct tevent_immediate *im = tevent_create_immediate(req);
3648 0 : if (!im) {
3649 0 : return NT_STATUS_NO_MEMORY;
3650 : }
3651 :
3652 0 : if (req->do_signing && firsttf->iov_len == 0) {
3653 0 : struct smbXsrv_session *x = req->session;
3654 : struct smb2_signing_key *signing_key =
3655 0 : smbd_smb2_signing_key(x, xconn, NULL);
3656 :
3657 : /*
3658 : * we need to remember the signing key
3659 : * and defer the signing until
3660 : * we are sure that we do not change
3661 : * the header again.
3662 : */
3663 0 : status = smb2_signing_key_copy(req,
3664 : signing_key,
3665 : &req->last_sign_key);
3666 0 : if (!NT_STATUS_IS_OK(status)) {
3667 0 : return status;
3668 : }
3669 : }
3670 :
3671 : /*
3672 : * smbd_smb2_request_dispatch() will redo the impersonation.
3673 : * So we use req->xconn->client->raw_ev_ctx instead
3674 : * of req->ev_ctx here.
3675 : */
3676 0 : tevent_schedule_immediate(im,
3677 : req->xconn->client->raw_ev_ctx,
3678 : smbd_smb2_request_dispatch_immediate,
3679 : req);
3680 0 : return NT_STATUS_OK;
3681 : }
3682 :
3683 159450 : if (req->compound_related) {
3684 0 : req->compound_related = false;
3685 : }
3686 :
3687 159450 : ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
3688 159450 : if (!ok) {
3689 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
3690 : }
3691 :
3692 : /* Set credit for these operations (zero credits if this
3693 : is a final reply for an async operation). */
3694 159450 : smb2_calculate_credits(req, req);
3695 :
3696 : /*
3697 : * now check if we need to sign the current response
3698 : */
3699 159450 : if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
3700 614 : status = smb2_signing_encrypt_pdu(req->first_enc_key,
3701 : firsttf,
3702 614 : req->out.vector_count - first_idx);
3703 614 : if (!NT_STATUS_IS_OK(status)) {
3704 0 : return status;
3705 : }
3706 158836 : } else if (req->do_signing) {
3707 129590 : struct smbXsrv_session *x = req->session;
3708 : struct smb2_signing_key *signing_key =
3709 129590 : smbd_smb2_signing_key(x, xconn, NULL);
3710 :
3711 129590 : status = smb2_signing_sign_pdu(signing_key,
3712 : outhdr,
3713 : SMBD_SMB2_NUM_IOV_PER_REQ - 1);
3714 129590 : if (!NT_STATUS_IS_OK(status)) {
3715 0 : return status;
3716 : }
3717 : }
3718 159450 : TALLOC_FREE(req->first_enc_key);
3719 :
3720 159450 : if (req->preauth != NULL) {
3721 4053 : gnutls_hash_hd_t hash_hnd = NULL;
3722 : size_t i;
3723 : int rc;
3724 :
3725 4053 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
3726 4053 : if (rc < 0) {
3727 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3728 : }
3729 4053 : rc = gnutls_hash(hash_hnd,
3730 4053 : req->preauth->sha512_value,
3731 : sizeof(req->preauth->sha512_value));
3732 4053 : if (rc < 0) {
3733 0 : gnutls_hash_deinit(hash_hnd, NULL);
3734 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3735 : }
3736 20265 : for (i = 1; i < req->in.vector_count; i++) {
3737 16212 : rc = gnutls_hash(hash_hnd,
3738 16212 : req->in.vector[i].iov_base,
3739 16212 : req->in.vector[i].iov_len);
3740 16212 : if (rc < 0) {
3741 0 : gnutls_hash_deinit(hash_hnd, NULL);
3742 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3743 : }
3744 : }
3745 4053 : if (rc < 0) {
3746 0 : gnutls_hash_deinit(hash_hnd, NULL);
3747 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3748 : }
3749 4053 : gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
3750 :
3751 4053 : rc = gnutls_hash(hash_hnd,
3752 4053 : req->preauth->sha512_value,
3753 : sizeof(req->preauth->sha512_value));
3754 4053 : if (rc < 0) {
3755 0 : gnutls_hash_deinit(hash_hnd, NULL);
3756 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3757 : }
3758 20265 : for (i = 1; i < req->out.vector_count; i++) {
3759 16212 : rc = gnutls_hash(hash_hnd,
3760 16212 : req->out.vector[i].iov_base,
3761 16212 : req->out.vector[i].iov_len);
3762 16212 : if (rc < 0) {
3763 0 : gnutls_hash_deinit(hash_hnd, NULL);
3764 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
3765 : }
3766 : }
3767 :
3768 4053 : gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
3769 :
3770 4053 : req->preauth = NULL;
3771 : }
3772 :
3773 : /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
3774 159450 : if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
3775 159450 : outdyn->iov_base == NULL && outdyn->iov_len != 0) {
3776 : /* Dynamic part is NULL. Chop it off,
3777 : We're going to send it via sendfile. */
3778 0 : req->out.vector_count -= 1;
3779 : }
3780 :
3781 : /*
3782 : * We're done with this request -
3783 : * move it off the "being processed" queue.
3784 : */
3785 159450 : DLIST_REMOVE(xconn->smb2.requests, req);
3786 :
3787 159450 : req->queue_entry.mem_ctx = req;
3788 159450 : req->queue_entry.vector = req->out.vector;
3789 159450 : req->queue_entry.count = req->out.vector_count;
3790 159450 : DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
3791 159450 : xconn->smb2.send_queue_len++;
3792 :
3793 159450 : status = smbd_smb2_flush_send_queue(xconn);
3794 159450 : if (!NT_STATUS_IS_OK(status)) {
3795 2428 : return status;
3796 : }
3797 :
3798 157022 : return NT_STATUS_OK;
3799 : }
3800 :
3801 : static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
3802 :
3803 0 : void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
3804 : struct tevent_immediate *im,
3805 : void *private_data)
3806 : {
3807 0 : struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
3808 : struct smbd_smb2_request);
3809 0 : struct smbXsrv_connection *xconn = req->xconn;
3810 : NTSTATUS status;
3811 :
3812 0 : TALLOC_FREE(im);
3813 :
3814 0 : if (DEBUGLEVEL >= 10) {
3815 0 : DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
3816 : req->current_idx, req->in.vector_count));
3817 0 : print_req_vectors(req);
3818 : }
3819 :
3820 0 : status = smbd_smb2_request_dispatch(req);
3821 0 : if (!NT_STATUS_IS_OK(status)) {
3822 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
3823 0 : return;
3824 : }
3825 :
3826 0 : status = smbd_smb2_request_next_incoming(xconn);
3827 0 : if (!NT_STATUS_IS_OK(status)) {
3828 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
3829 0 : return;
3830 : }
3831 : }
3832 :
3833 159450 : NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
3834 : NTSTATUS status,
3835 : DATA_BLOB body, DATA_BLOB *dyn,
3836 : const char *location)
3837 : {
3838 : uint8_t *outhdr;
3839 : struct iovec *outbody_v;
3840 : struct iovec *outdyn_v;
3841 : uint32_t next_command_ofs;
3842 : uint64_t mid;
3843 :
3844 159450 : outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3845 159450 : mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
3846 :
3847 159450 : DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
3848 : "body[%u] dyn[%s:%u] at %s\n",
3849 : mid,
3850 : req->current_idx,
3851 : nt_errstr(status),
3852 : (unsigned int)body.length,
3853 : dyn ? "yes" : "no",
3854 : (unsigned int)(dyn ? dyn->length : 0),
3855 : location);
3856 :
3857 159450 : if (body.length < 2) {
3858 0 : return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3859 : }
3860 :
3861 159450 : if ((body.length % 2) != 0) {
3862 0 : return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
3863 : }
3864 :
3865 159450 : outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
3866 159450 : outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
3867 :
3868 159450 : next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
3869 159450 : SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
3870 :
3871 159450 : outbody_v->iov_base = (void *)body.data;
3872 159450 : outbody_v->iov_len = body.length;
3873 :
3874 159450 : if (dyn) {
3875 133992 : outdyn_v->iov_base = (void *)dyn->data;
3876 133992 : outdyn_v->iov_len = dyn->length;
3877 : } else {
3878 25458 : outdyn_v->iov_base = NULL;
3879 25458 : outdyn_v->iov_len = 0;
3880 : }
3881 :
3882 : /*
3883 : * See if we need to recalculate the offset to the next response
3884 : *
3885 : * Note that all responses may require padding (including the very last
3886 : * one).
3887 : */
3888 159450 : if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
3889 0 : next_command_ofs = SMB2_HDR_BODY;
3890 0 : next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
3891 0 : next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
3892 : }
3893 :
3894 159450 : if ((next_command_ofs % 8) != 0) {
3895 0 : size_t pad_size = 8 - (next_command_ofs % 8);
3896 0 : if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
3897 : /*
3898 : * if the dyn buffer is empty
3899 : * we can use it to add padding
3900 : */
3901 : uint8_t *pad;
3902 :
3903 0 : pad = talloc_zero_array(req,
3904 : uint8_t, pad_size);
3905 0 : if (pad == NULL) {
3906 0 : return smbd_smb2_request_error(req,
3907 : NT_STATUS_NO_MEMORY);
3908 : }
3909 :
3910 0 : outdyn_v->iov_base = (void *)pad;
3911 0 : outdyn_v->iov_len = pad_size;
3912 : } else {
3913 : /*
3914 : * For now we copy the dynamic buffer
3915 : * and add the padding to the new buffer
3916 : */
3917 : size_t old_size;
3918 : uint8_t *old_dyn;
3919 : size_t new_size;
3920 : uint8_t *new_dyn;
3921 :
3922 0 : old_size = SMBD_SMB2_OUT_DYN_LEN(req);
3923 0 : old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
3924 :
3925 0 : new_size = old_size + pad_size;
3926 0 : new_dyn = talloc_zero_array(req,
3927 : uint8_t, new_size);
3928 0 : if (new_dyn == NULL) {
3929 0 : return smbd_smb2_request_error(req,
3930 : NT_STATUS_NO_MEMORY);
3931 : }
3932 :
3933 0 : memcpy(new_dyn, old_dyn, old_size);
3934 0 : memset(new_dyn + old_size, 0, pad_size);
3935 :
3936 0 : outdyn_v->iov_base = (void *)new_dyn;
3937 0 : outdyn_v->iov_len = new_size;
3938 : }
3939 0 : next_command_ofs += pad_size;
3940 : }
3941 :
3942 159450 : if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
3943 159450 : SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
3944 : } else {
3945 0 : SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
3946 : }
3947 159450 : return smbd_smb2_request_reply(req);
3948 : }
3949 :
3950 5449 : NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
3951 : NTSTATUS status,
3952 : uint8_t error_context_count,
3953 : DATA_BLOB *info,
3954 : const char *location)
3955 : {
3956 5449 : struct smbXsrv_connection *xconn = req->xconn;
3957 : DATA_BLOB body;
3958 : DATA_BLOB _dyn;
3959 5449 : uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
3960 5449 : size_t unread_bytes = smbd_smb2_unread_bytes(req);
3961 :
3962 5449 : DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
3963 : "at %s\n", req->current_idx, nt_errstr(status),
3964 : info ? " +info" : "", location);
3965 :
3966 5449 : if (unread_bytes) {
3967 : /* Recvfile error. Drain incoming socket. */
3968 : size_t ret;
3969 :
3970 0 : errno = 0;
3971 0 : ret = drain_socket(xconn->transport.sock, unread_bytes);
3972 0 : if (ret != unread_bytes) {
3973 : NTSTATUS error;
3974 :
3975 0 : if (errno == 0) {
3976 0 : error = NT_STATUS_IO_DEVICE_ERROR;
3977 : } else {
3978 0 : error = map_nt_error_from_unix_common(errno);
3979 : }
3980 :
3981 0 : DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
3982 : "ret[%u] errno[%d] => %s\n",
3983 : (unsigned)unread_bytes,
3984 : (unsigned)ret, errno, nt_errstr(error)));
3985 0 : return error;
3986 : }
3987 : }
3988 :
3989 5449 : body.data = outhdr + SMB2_HDR_BODY;
3990 5449 : body.length = 8;
3991 5449 : SSVAL(body.data, 0, 9);
3992 5449 : SCVAL(body.data, 2, error_context_count);
3993 :
3994 5449 : if (info) {
3995 0 : SIVAL(body.data, 0x04, info->length);
3996 : } else {
3997 : /* Allocated size of req->out.vector[i].iov_base
3998 : * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
3999 : * 1 byte without having to do an alloc.
4000 : */
4001 5449 : info = &_dyn;
4002 5449 : info->data = ((uint8_t *)outhdr) +
4003 5449 : OUTVEC_ALLOC_SIZE - 1;
4004 5449 : info->length = 1;
4005 5449 : SCVAL(info->data, 0, 0);
4006 : }
4007 :
4008 : /*
4009 : * Note: Even if there is an error, continue to process the request.
4010 : * per MS-SMB2.
4011 : */
4012 :
4013 5449 : return smbd_smb2_request_done_ex(req, status, body, info, __location__);
4014 : }
4015 :
4016 : struct smbd_smb2_break_state {
4017 : struct tevent_req *req;
4018 : struct smbd_smb2_send_queue queue_entry;
4019 : uint8_t nbt_hdr[NBT_HDR_SIZE];
4020 : uint8_t hdr[SMB2_HDR_BODY];
4021 : struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
4022 : };
4023 :
4024 0 : static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
4025 : struct tevent_context *ev,
4026 : struct smbXsrv_connection *xconn,
4027 : uint64_t session_id,
4028 : const uint8_t *body,
4029 : size_t body_len)
4030 : {
4031 0 : struct tevent_req *req = NULL;
4032 0 : struct smbd_smb2_break_state *state = NULL;
4033 : NTSTATUS status;
4034 : bool ok;
4035 :
4036 0 : req = tevent_req_create(mem_ctx, &state,
4037 : struct smbd_smb2_break_state);
4038 0 : if (req == NULL) {
4039 0 : return NULL;
4040 : }
4041 :
4042 0 : state->req = req;
4043 0 : tevent_req_defer_callback(req, ev);
4044 :
4045 0 : SIVAL(state->hdr, 0, SMB2_MAGIC);
4046 0 : SSVAL(state->hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
4047 0 : SSVAL(state->hdr, SMB2_HDR_EPOCH, 0);
4048 0 : SIVAL(state->hdr, SMB2_HDR_STATUS, 0);
4049 0 : SSVAL(state->hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
4050 0 : SSVAL(state->hdr, SMB2_HDR_CREDIT, 0);
4051 0 : SIVAL(state->hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
4052 0 : SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND, 0);
4053 0 : SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
4054 0 : SIVAL(state->hdr, SMB2_HDR_PID, 0);
4055 0 : SIVAL(state->hdr, SMB2_HDR_TID, 0);
4056 0 : SBVAL(state->hdr, SMB2_HDR_SESSION_ID, session_id);
4057 0 : memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
4058 :
4059 0 : state->vector[0] = (struct iovec) {
4060 0 : .iov_base = state->nbt_hdr,
4061 : .iov_len = sizeof(state->nbt_hdr)
4062 : };
4063 :
4064 0 : state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
4065 : .iov_base = NULL,
4066 : .iov_len = 0
4067 : };
4068 :
4069 0 : state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
4070 0 : .iov_base = state->hdr,
4071 : .iov_len = sizeof(state->hdr)
4072 : };
4073 :
4074 0 : state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
4075 : .iov_base = discard_const_p(uint8_t, body),
4076 : .iov_len = body_len,
4077 : };
4078 :
4079 : /*
4080 : * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
4081 : */
4082 :
4083 0 : ok = smb2_setup_nbt_length(state->vector,
4084 : 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
4085 0 : if (!ok) {
4086 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
4087 0 : return tevent_req_post(req, ev);
4088 : }
4089 :
4090 : /*
4091 : * We require TCP acks for this PDU to the client!
4092 : * We want 5 retransmissions and timeout when the
4093 : * retransmission timeout (rto) passed 6 times.
4094 : *
4095 : * required_acked_bytes gets a dummy value of
4096 : * UINT64_MAX, as long it's in xconn->smb2.send_queue,
4097 : * it'll get the real value when it's moved to
4098 : * xconn->ack.queue.
4099 : *
4100 : * state->queue_entry.ack.req gets completed with
4101 : * 1. tevent_req_done(), when all bytes are acked.
4102 : * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
4103 : * the timeout expired before all bytes were acked.
4104 : * 2b. tevent_req_nterror(transport_error), when the
4105 : * connection got a disconnect from the kernel.
4106 : */
4107 0 : state->queue_entry.ack.timeout =
4108 0 : timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
4109 0 : state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
4110 0 : state->queue_entry.ack.req = req;
4111 0 : state->queue_entry.mem_ctx = state;
4112 0 : state->queue_entry.vector = state->vector;
4113 0 : state->queue_entry.count = ARRAY_SIZE(state->vector);
4114 0 : DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
4115 0 : xconn->smb2.send_queue_len++;
4116 :
4117 0 : status = smbd_smb2_flush_send_queue(xconn);
4118 0 : if (tevent_req_nterror(req, status)) {
4119 0 : return tevent_req_post(req, ev);
4120 : }
4121 :
4122 0 : return req;
4123 : }
4124 :
4125 0 : static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
4126 : {
4127 0 : return tevent_req_simple_recv_ntstatus(req);
4128 : }
4129 :
4130 : struct smbXsrv_pending_break {
4131 : struct smbXsrv_pending_break *prev, *next;
4132 : struct smbXsrv_client *client;
4133 : bool disable_oplock_break_retries;
4134 : uint64_t session_id;
4135 : uint64_t last_channel_id;
4136 : union {
4137 : uint8_t generic[1];
4138 : uint8_t oplock[0x18];
4139 : uint8_t lease[0x2c];
4140 : } body;
4141 : size_t body_len;
4142 : };
4143 :
4144 : static void smbXsrv_pending_break_done(struct tevent_req *subreq);
4145 :
4146 0 : static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
4147 : struct smbXsrv_client *client,
4148 : uint64_t session_id)
4149 : {
4150 0 : struct smbXsrv_pending_break *pb = NULL;
4151 :
4152 0 : pb = talloc_zero(client, struct smbXsrv_pending_break);
4153 0 : if (pb == NULL) {
4154 0 : return NULL;
4155 : }
4156 0 : pb->client = client;
4157 0 : pb->session_id = session_id;
4158 0 : pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
4159 :
4160 0 : return pb;
4161 : }
4162 :
4163 : static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
4164 :
4165 0 : static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
4166 : {
4167 0 : struct smbXsrv_client *client = pb->client;
4168 : NTSTATUS status;
4169 :
4170 0 : DLIST_ADD_END(client->pending_breaks, pb);
4171 0 : status = smbXsrv_client_pending_breaks_updated(client);
4172 0 : if (!NT_STATUS_IS_OK(status)) {
4173 0 : return status;
4174 : }
4175 :
4176 0 : status = smbXsrv_pending_break_submit(pb);
4177 0 : if (!NT_STATUS_IS_OK(status)) {
4178 0 : return status;
4179 : }
4180 :
4181 0 : return NT_STATUS_OK;
4182 : }
4183 :
4184 0 : static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
4185 : {
4186 0 : struct smbXsrv_client *client = pb->client;
4187 0 : struct smbXsrv_session *session = NULL;
4188 0 : struct smbXsrv_connection *xconn = NULL;
4189 0 : struct smbXsrv_connection *oplock_xconn = NULL;
4190 0 : struct tevent_req *subreq = NULL;
4191 : NTSTATUS status;
4192 :
4193 0 : if (pb->session_id != 0) {
4194 0 : status = get_valid_smbXsrv_session(client,
4195 : pb->session_id,
4196 : &session);
4197 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
4198 0 : return NT_STATUS_ABANDONED;
4199 : }
4200 0 : if (!NT_STATUS_IS_OK(status)) {
4201 0 : return status;
4202 : }
4203 :
4204 0 : if (pb->last_channel_id != 0) {
4205 : /*
4206 : * This is what current Windows servers
4207 : * do, they don't retry on all available
4208 : * channels. They only use the last channel.
4209 : *
4210 : * But it doesn't match the specification in
4211 : * [MS-SMB2] "3.3.4.6 Object Store Indicates an
4212 : * Oplock Break"
4213 : *
4214 : * Per default disable_oplock_break_retries is false
4215 : * and we behave like the specification.
4216 : */
4217 0 : if (pb->disable_oplock_break_retries) {
4218 0 : return NT_STATUS_ABANDONED;
4219 : }
4220 : }
4221 : }
4222 :
4223 0 : for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
4224 0 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4225 0 : continue;
4226 : }
4227 :
4228 0 : if (xconn->channel_id == 0) {
4229 : /*
4230 : * non-multichannel case
4231 : */
4232 0 : break;
4233 : }
4234 :
4235 0 : if (session != NULL) {
4236 0 : struct smbXsrv_channel_global0 *c = NULL;
4237 :
4238 : /*
4239 : * Having a session means we're handling
4240 : * an oplock break and we only need to
4241 : * use channels available on the
4242 : * session.
4243 : */
4244 0 : status = smbXsrv_session_find_channel(session, xconn, &c);
4245 0 : if (!NT_STATUS_IS_OK(status)) {
4246 0 : continue;
4247 : }
4248 :
4249 : /*
4250 : * This is what current Windows servers
4251 : * do, they don't retry on all available
4252 : * channels. They only use the last channel.
4253 : *
4254 : * But it doesn't match the specification
4255 : * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
4256 : * Oplock Break"
4257 : *
4258 : * Per default disable_oplock_break_retries is false
4259 : * and we behave like the specification.
4260 : */
4261 0 : if (pb->disable_oplock_break_retries) {
4262 0 : oplock_xconn = xconn;
4263 0 : continue;
4264 : }
4265 : }
4266 :
4267 0 : if (xconn->channel_id > pb->last_channel_id) {
4268 : /*
4269 : * multichannel case
4270 : */
4271 0 : break;
4272 : }
4273 : }
4274 :
4275 0 : if (xconn == NULL) {
4276 0 : xconn = oplock_xconn;
4277 : }
4278 :
4279 0 : if (xconn == NULL) {
4280 : /*
4281 : * If there's no remaining connection available
4282 : * tell the caller to stop...
4283 : */
4284 0 : return NT_STATUS_ABANDONED;
4285 : }
4286 :
4287 0 : pb->last_channel_id = xconn->channel_id;
4288 :
4289 0 : subreq = smbd_smb2_break_send(pb,
4290 : client->raw_ev_ctx,
4291 : xconn,
4292 : pb->session_id,
4293 0 : pb->body.generic,
4294 : pb->body_len);
4295 0 : if (subreq == NULL) {
4296 0 : return NT_STATUS_NO_MEMORY;
4297 : }
4298 0 : tevent_req_set_callback(subreq,
4299 : smbXsrv_pending_break_done,
4300 : pb);
4301 :
4302 0 : return NT_STATUS_OK;
4303 : }
4304 :
4305 0 : static void smbXsrv_pending_break_done(struct tevent_req *subreq)
4306 : {
4307 : struct smbXsrv_pending_break *pb =
4308 0 : tevent_req_callback_data(subreq,
4309 : struct smbXsrv_pending_break);
4310 0 : struct smbXsrv_client *client = pb->client;
4311 : NTSTATUS status;
4312 :
4313 0 : status = smbd_smb2_break_recv(subreq);
4314 0 : TALLOC_FREE(subreq);
4315 0 : if (!NT_STATUS_IS_OK(status)) {
4316 0 : status = smbXsrv_pending_break_submit(pb);
4317 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
4318 : /*
4319 : * If there's no remaing connection
4320 : * there's no need to send a break again.
4321 : */
4322 0 : goto remove;
4323 : }
4324 0 : if (!NT_STATUS_IS_OK(status)) {
4325 0 : smbd_server_disconnect_client(client, nt_errstr(status));
4326 0 : return;
4327 : }
4328 0 : return;
4329 : }
4330 :
4331 0 : remove:
4332 0 : DLIST_REMOVE(client->pending_breaks, pb);
4333 0 : TALLOC_FREE(pb);
4334 :
4335 0 : status = smbXsrv_client_pending_breaks_updated(client);
4336 0 : if (!NT_STATUS_IS_OK(status)) {
4337 0 : smbd_server_disconnect_client(client, nt_errstr(status));
4338 0 : return;
4339 : }
4340 : }
4341 :
4342 0 : NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
4343 : struct smbXsrv_open *op,
4344 : uint8_t oplock_level)
4345 : {
4346 0 : struct smbXsrv_pending_break *pb = NULL;
4347 0 : uint8_t *body = NULL;
4348 :
4349 0 : pb = smbXsrv_pending_break_create(client,
4350 0 : op->compat->vuid);
4351 0 : if (pb == NULL) {
4352 0 : return NT_STATUS_NO_MEMORY;
4353 : }
4354 0 : pb->body_len = sizeof(pb->body.oplock);
4355 0 : body = pb->body.oplock;
4356 :
4357 0 : SSVAL(body, 0x00, pb->body_len);
4358 0 : SCVAL(body, 0x02, oplock_level);
4359 0 : SCVAL(body, 0x03, 0); /* reserved */
4360 0 : SIVAL(body, 0x04, 0); /* reserved */
4361 0 : SBVAL(body, 0x08, op->global->open_persistent_id);
4362 0 : SBVAL(body, 0x10, op->global->open_volatile_id);
4363 :
4364 0 : return smbXsrv_pending_break_schedule(pb);
4365 : }
4366 :
4367 0 : NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
4368 : uint16_t new_epoch,
4369 : uint32_t lease_flags,
4370 : struct smb2_lease_key *lease_key,
4371 : uint32_t current_lease_state,
4372 : uint32_t new_lease_state)
4373 : {
4374 0 : struct smbXsrv_pending_break *pb = NULL;
4375 0 : uint8_t *body = NULL;
4376 :
4377 0 : pb = smbXsrv_pending_break_create(client,
4378 : 0); /* no session_id */
4379 0 : if (pb == NULL) {
4380 0 : return NT_STATUS_NO_MEMORY;
4381 : }
4382 0 : pb->body_len = sizeof(pb->body.lease);
4383 0 : body = pb->body.lease;
4384 :
4385 0 : SSVAL(body, 0x00, pb->body_len);
4386 0 : SSVAL(body, 0x02, new_epoch);
4387 0 : SIVAL(body, 0x04, lease_flags);
4388 0 : SBVAL(body, 0x08, lease_key->data[0]);
4389 0 : SBVAL(body, 0x10, lease_key->data[1]);
4390 0 : SIVAL(body, 0x18, current_lease_state);
4391 0 : SIVAL(body, 0x1c, new_lease_state);
4392 0 : SIVAL(body, 0x20, 0); /* BreakReason, MUST be 0 */
4393 0 : SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */
4394 0 : SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */
4395 :
4396 0 : return smbXsrv_pending_break_schedule(pb);
4397 : }
4398 :
4399 0 : static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
4400 : {
4401 : NTSTATUS status;
4402 : uint32_t flags;
4403 : uint64_t file_id_persistent;
4404 : uint64_t file_id_volatile;
4405 0 : struct smbXsrv_open *op = NULL;
4406 0 : struct files_struct *fsp = NULL;
4407 0 : const uint8_t *body = NULL;
4408 :
4409 : /*
4410 : * This is only called with a pktbuf
4411 : * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
4412 : * bytes
4413 : */
4414 :
4415 0 : if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
4416 : /* Transform header. Cannot recvfile. */
4417 0 : return false;
4418 : }
4419 0 : if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
4420 : /* Not SMB2. Normal error path will cope. */
4421 0 : return false;
4422 : }
4423 0 : if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
4424 : /* Not SMB2. Normal error path will cope. */
4425 0 : return false;
4426 : }
4427 0 : if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
4428 : /* Needs to be a WRITE. */
4429 0 : return false;
4430 : }
4431 0 : if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
4432 : /* Chained. Cannot recvfile. */
4433 0 : return false;
4434 : }
4435 0 : flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
4436 0 : if (flags & SMB2_HDR_FLAG_CHAINED) {
4437 : /* Chained. Cannot recvfile. */
4438 0 : return false;
4439 : }
4440 0 : if (flags & SMB2_HDR_FLAG_SIGNED) {
4441 : /* Signed. Cannot recvfile. */
4442 0 : return false;
4443 : }
4444 :
4445 0 : body = &state->pktbuf[SMB2_HDR_BODY];
4446 :
4447 0 : file_id_persistent = BVAL(body, 0x10);
4448 0 : file_id_volatile = BVAL(body, 0x18);
4449 :
4450 0 : status = smb2srv_open_lookup(state->req->xconn,
4451 : file_id_persistent,
4452 : file_id_volatile,
4453 : 0, /* now */
4454 : &op);
4455 0 : if (!NT_STATUS_IS_OK(status)) {
4456 0 : return false;
4457 : }
4458 :
4459 0 : fsp = op->compat;
4460 0 : if (fsp == NULL) {
4461 0 : return false;
4462 : }
4463 0 : if (fsp->conn == NULL) {
4464 0 : return false;
4465 : }
4466 :
4467 0 : if (IS_IPC(fsp->conn)) {
4468 0 : return false;
4469 : }
4470 0 : if (IS_PRINT(fsp->conn)) {
4471 0 : return false;
4472 : }
4473 0 : if (fsp_is_alternate_stream(fsp)) {
4474 0 : return false;
4475 : }
4476 :
4477 0 : DEBUG(10,("Doing recvfile write len = %u\n",
4478 : (unsigned int)(state->pktfull - state->pktlen)));
4479 :
4480 0 : return true;
4481 : }
4482 :
4483 334171 : static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
4484 : {
4485 334171 : struct smbd_server_connection *sconn = xconn->client->sconn;
4486 334171 : struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4487 : size_t max_send_queue_len;
4488 : size_t cur_send_queue_len;
4489 :
4490 334171 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4491 : /*
4492 : * we're not supposed to do any io
4493 : */
4494 0 : return NT_STATUS_OK;
4495 : }
4496 :
4497 334171 : if (state->req != NULL) {
4498 : /*
4499 : * if there is already a tstream_readv_pdu
4500 : * pending, we are done.
4501 : */
4502 177081 : return NT_STATUS_OK;
4503 : }
4504 :
4505 157090 : max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
4506 157090 : cur_send_queue_len = xconn->smb2.send_queue_len;
4507 :
4508 157090 : if (cur_send_queue_len > max_send_queue_len) {
4509 : /*
4510 : * if we have a lot of requests to send,
4511 : * we wait until they are on the wire until we
4512 : * ask for the next request.
4513 : */
4514 0 : return NT_STATUS_OK;
4515 : }
4516 :
4517 : /* ask for the next request */
4518 157090 : ZERO_STRUCTP(state);
4519 157090 : state->req = smbd_smb2_request_allocate(xconn);
4520 157090 : if (state->req == NULL) {
4521 0 : return NT_STATUS_NO_MEMORY;
4522 : }
4523 157090 : state->req->sconn = sconn;
4524 157090 : state->req->xconn = xconn;
4525 157090 : state->min_recv_size = lp_min_receive_file_size();
4526 :
4527 157090 : TEVENT_FD_READABLE(xconn->transport.fde);
4528 :
4529 157090 : return NT_STATUS_OK;
4530 : }
4531 :
4532 5046 : NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
4533 : uint64_t expected_seq_low,
4534 : const uint8_t *inpdu, size_t size)
4535 : {
4536 5046 : struct smbd_server_connection *sconn = xconn->client->sconn;
4537 : NTSTATUS status;
4538 5046 : struct smbd_smb2_request *req = NULL;
4539 :
4540 5046 : DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
4541 : (unsigned int)size));
4542 :
4543 5046 : status = smbd_initialize_smb2(xconn, expected_seq_low);
4544 5046 : if (!NT_STATUS_IS_OK(status)) {
4545 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
4546 0 : return status;
4547 : }
4548 :
4549 : /*
4550 : * If a new connection joins the process, when we're
4551 : * already in a "pending break cycle", we need to
4552 : * turn on the ack checker on the new connection.
4553 : */
4554 5046 : status = smbXsrv_client_pending_breaks_updated(xconn->client);
4555 5046 : if (!NT_STATUS_IS_OK(status)) {
4556 : /*
4557 : * If there's a problem, we disconnect the whole
4558 : * client with all connections here!
4559 : *
4560 : * Instead of just the new connection.
4561 : */
4562 0 : smbd_server_disconnect_client(xconn->client, nt_errstr(status));
4563 0 : return status;
4564 : }
4565 :
4566 5046 : status = smbd_smb2_request_create(xconn, inpdu, size, &req);
4567 5046 : if (!NT_STATUS_IS_OK(status)) {
4568 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
4569 0 : return status;
4570 : }
4571 :
4572 5046 : status = smbd_smb2_request_validate(req);
4573 5046 : if (!NT_STATUS_IS_OK(status)) {
4574 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
4575 0 : return status;
4576 : }
4577 :
4578 5046 : status = smbd_smb2_request_setup_out(req);
4579 5046 : if (!NT_STATUS_IS_OK(status)) {
4580 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
4581 0 : return status;
4582 : }
4583 :
4584 : #ifdef WITH_PROFILE
4585 : /*
4586 : * this was already counted at the SMB1 layer =>
4587 : * smbd_smb2_request_dispatch() should not count it twice.
4588 : */
4589 5046 : if (profile_p->values.request_stats.count > 0) {
4590 0 : profile_p->values.request_stats.count--;
4591 : }
4592 : #endif
4593 5046 : status = smbd_smb2_request_dispatch(req);
4594 5046 : if (!NT_STATUS_IS_OK(status)) {
4595 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
4596 0 : return status;
4597 : }
4598 :
4599 5046 : status = smbd_smb2_request_next_incoming(xconn);
4600 5046 : if (!NT_STATUS_IS_OK(status)) {
4601 0 : smbd_server_connection_terminate(xconn, nt_errstr(status));
4602 0 : return status;
4603 : }
4604 :
4605 5046 : sconn->num_requests++;
4606 5046 : return NT_STATUS_OK;
4607 : }
4608 :
4609 671942 : static int socket_error_from_errno(int ret,
4610 : int sys_errno,
4611 : bool *retry)
4612 : {
4613 671942 : *retry = false;
4614 :
4615 671942 : if (ret >= 0) {
4616 669171 : return 0;
4617 : }
4618 :
4619 2771 : if (ret != -1) {
4620 0 : return EIO;
4621 : }
4622 :
4623 2771 : if (sys_errno == 0) {
4624 0 : return EIO;
4625 : }
4626 :
4627 2771 : if (sys_errno == EINTR) {
4628 0 : *retry = true;
4629 0 : return sys_errno;
4630 : }
4631 :
4632 2771 : if (sys_errno == EINPROGRESS) {
4633 0 : *retry = true;
4634 0 : return sys_errno;
4635 : }
4636 :
4637 2771 : if (sys_errno == EAGAIN) {
4638 0 : *retry = true;
4639 0 : return sys_errno;
4640 : }
4641 :
4642 : /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
4643 2771 : if (sys_errno == ENOMEM) {
4644 0 : *retry = true;
4645 0 : return sys_errno;
4646 : }
4647 :
4648 : #ifdef EWOULDBLOCK
4649 : #if EWOULDBLOCK != EAGAIN
4650 : if (sys_errno == EWOULDBLOCK) {
4651 : *retry = true;
4652 : return sys_errno;
4653 : }
4654 : #endif
4655 : #endif
4656 :
4657 2771 : return sys_errno;
4658 : }
4659 :
4660 272242 : static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
4661 : {
4662 : int ret;
4663 : int err;
4664 : bool retry;
4665 : NTSTATUS status;
4666 :
4667 272242 : if (xconn->smb2.send_queue == NULL) {
4668 5689 : TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4669 5689 : return NT_STATUS_OK;
4670 : }
4671 :
4672 443646 : while (xconn->smb2.send_queue != NULL) {
4673 266565 : struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
4674 : bool ok;
4675 : struct msghdr msg;
4676 :
4677 266565 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4678 : /*
4679 : * we're not supposed to do any io
4680 : * just flush all pending stuff.
4681 : */
4682 0 : xconn->smb2.send_queue_len--;
4683 0 : DLIST_REMOVE(xconn->smb2.send_queue, e);
4684 :
4685 0 : talloc_free(e->mem_ctx);
4686 177093 : continue;
4687 : }
4688 :
4689 266565 : if (e->sendfile_header != NULL) {
4690 0 : size_t size = 0;
4691 0 : size_t i = 0;
4692 : uint8_t *buf;
4693 :
4694 0 : status = NT_STATUS_INTERNAL_ERROR;
4695 :
4696 0 : for (i=0; i < e->count; i++) {
4697 0 : size += e->vector[i].iov_len;
4698 : }
4699 :
4700 0 : if (size <= e->sendfile_header->length) {
4701 0 : buf = e->sendfile_header->data;
4702 : } else {
4703 0 : buf = talloc_array(e->mem_ctx, uint8_t, size);
4704 0 : if (buf == NULL) {
4705 0 : return NT_STATUS_NO_MEMORY;
4706 : }
4707 : }
4708 :
4709 0 : size = 0;
4710 0 : for (i=0; i < e->count; i++) {
4711 0 : memcpy(buf+size,
4712 0 : e->vector[i].iov_base,
4713 0 : e->vector[i].iov_len);
4714 0 : size += e->vector[i].iov_len;
4715 : }
4716 :
4717 0 : e->sendfile_header->data = buf;
4718 0 : e->sendfile_header->length = size;
4719 0 : e->sendfile_status = &status;
4720 0 : e->count = 0;
4721 :
4722 0 : xconn->smb2.send_queue_len--;
4723 0 : DLIST_REMOVE(xconn->smb2.send_queue, e);
4724 :
4725 0 : size += e->sendfile_body_size;
4726 :
4727 : /*
4728 : * This triggers the sendfile path via
4729 : * the destructor.
4730 : */
4731 0 : talloc_free(e->mem_ctx);
4732 :
4733 0 : if (!NT_STATUS_IS_OK(status)) {
4734 0 : smbXsrv_connection_disconnect_transport(xconn,
4735 : status);
4736 0 : return status;
4737 : }
4738 0 : xconn->ack.unacked_bytes += size;
4739 0 : continue;
4740 : }
4741 :
4742 266565 : msg = (struct msghdr) {
4743 266565 : .msg_iov = e->vector,
4744 266565 : .msg_iovlen = e->count,
4745 : };
4746 :
4747 266565 : ret = sendmsg(xconn->transport.sock, &msg, 0);
4748 266565 : if (ret == 0) {
4749 : /* propagate end of file */
4750 0 : return NT_STATUS_INTERNAL_ERROR;
4751 : }
4752 266565 : err = socket_error_from_errno(ret, errno, &retry);
4753 266565 : if (retry) {
4754 : /* retry later */
4755 0 : TEVENT_FD_WRITEABLE(xconn->transport.fde);
4756 0 : return NT_STATUS_OK;
4757 : }
4758 266565 : if (err != 0) {
4759 2428 : status = map_nt_error_from_unix_common(err);
4760 2428 : smbXsrv_connection_disconnect_transport(xconn,
4761 : status);
4762 2428 : return status;
4763 : }
4764 :
4765 264137 : xconn->ack.unacked_bytes += ret;
4766 :
4767 264137 : ok = iov_advance(&e->vector, &e->count, ret);
4768 264137 : if (!ok) {
4769 0 : return NT_STATUS_INTERNAL_ERROR;
4770 : }
4771 :
4772 264137 : if (e->count > 0) {
4773 : /* we have more to write */
4774 87044 : TEVENT_FD_WRITEABLE(xconn->transport.fde);
4775 87044 : return NT_STATUS_OK;
4776 : }
4777 :
4778 177093 : xconn->smb2.send_queue_len--;
4779 177093 : DLIST_REMOVE(xconn->smb2.send_queue, e);
4780 :
4781 177093 : if (e->ack.req == NULL) {
4782 177093 : talloc_free(e->mem_ctx);
4783 177093 : continue;
4784 : }
4785 :
4786 0 : e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
4787 0 : DLIST_ADD_END(xconn->ack.queue, e);
4788 : }
4789 :
4790 : /*
4791 : * Restart reads if we were blocked on
4792 : * draining the send queue.
4793 : */
4794 :
4795 177081 : status = smbd_smb2_request_next_incoming(xconn);
4796 177081 : if (!NT_STATUS_IS_OK(status)) {
4797 0 : return status;
4798 : }
4799 :
4800 177081 : return NT_STATUS_OK;
4801 : }
4802 :
4803 345818 : static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
4804 : uint16_t fde_flags)
4805 : {
4806 345818 : struct smbd_server_connection *sconn = xconn->client->sconn;
4807 345818 : struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
4808 345818 : struct smbd_smb2_request *req = NULL;
4809 345818 : size_t min_recvfile_size = UINT32_MAX;
4810 : int ret;
4811 : int err;
4812 : bool retry;
4813 : NTSTATUS status;
4814 : NTTIME now;
4815 : struct msghdr msg;
4816 :
4817 345818 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
4818 : /*
4819 : * we're not supposed to do any io
4820 : */
4821 0 : TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4822 0 : TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
4823 0 : return NT_STATUS_OK;
4824 : }
4825 :
4826 345818 : if (fde_flags & TEVENT_FD_WRITE) {
4827 92721 : status = smbd_smb2_flush_send_queue(xconn);
4828 92721 : if (!NT_STATUS_IS_OK(status)) {
4829 0 : return status;
4830 : }
4831 : }
4832 :
4833 345818 : if (!(fde_flags & TEVENT_FD_READ)) {
4834 92703 : return NT_STATUS_OK;
4835 : }
4836 :
4837 253115 : if (state->req == NULL) {
4838 0 : TEVENT_FD_NOT_READABLE(xconn->transport.fde);
4839 0 : return NT_STATUS_OK;
4840 : }
4841 :
4842 288462 : again:
4843 407587 : if (!state->hdr.done) {
4844 157025 : state->hdr.done = true;
4845 :
4846 157025 : state->vector.iov_base = (void *)state->hdr.nbt;
4847 157025 : state->vector.iov_len = NBT_HDR_SIZE;
4848 : }
4849 :
4850 407587 : msg = (struct msghdr) {
4851 407587 : .msg_iov = &state->vector,
4852 : .msg_iovlen = 1,
4853 : };
4854 :
4855 407587 : ret = recvmsg(xconn->transport.sock, &msg, 0);
4856 407587 : if (ret == 0) {
4857 : /* propagate end of file */
4858 2210 : status = NT_STATUS_END_OF_FILE;
4859 2210 : smbXsrv_connection_disconnect_transport(xconn,
4860 : status);
4861 2210 : return status;
4862 : }
4863 405377 : err = socket_error_from_errno(ret, errno, &retry);
4864 405377 : if (retry) {
4865 : /* retry later */
4866 0 : TEVENT_FD_READABLE(xconn->transport.fde);
4867 0 : return NT_STATUS_OK;
4868 : }
4869 405377 : if (err != 0) {
4870 343 : status = map_nt_error_from_unix_common(err);
4871 343 : smbXsrv_connection_disconnect_transport(xconn,
4872 : status);
4873 343 : return status;
4874 : }
4875 :
4876 405034 : if (ret < state->vector.iov_len) {
4877 : uint8_t *base;
4878 96090 : base = (uint8_t *)state->vector.iov_base;
4879 96090 : base += ret;
4880 96090 : state->vector.iov_base = (void *)base;
4881 96090 : state->vector.iov_len -= ret;
4882 : /* we have more to read */
4883 96090 : TEVENT_FD_READABLE(xconn->transport.fde);
4884 96090 : return NT_STATUS_OK;
4885 : }
4886 :
4887 308944 : if (state->pktlen > 0) {
4888 154472 : if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
4889 : /*
4890 : * Not a possible receivefile write.
4891 : * Read the rest of the data.
4892 : */
4893 0 : state->doing_receivefile = false;
4894 :
4895 0 : state->pktbuf = talloc_realloc(state->req,
4896 : state->pktbuf,
4897 : uint8_t,
4898 : state->pktfull);
4899 0 : if (state->pktbuf == NULL) {
4900 0 : return NT_STATUS_NO_MEMORY;
4901 : }
4902 :
4903 0 : state->vector.iov_base = (void *)(state->pktbuf +
4904 0 : state->pktlen);
4905 0 : state->vector.iov_len = (state->pktfull -
4906 0 : state->pktlen);
4907 :
4908 0 : state->pktlen = state->pktfull;
4909 0 : goto again;
4910 : }
4911 :
4912 : /*
4913 : * Either this is a receivefile write so we've
4914 : * done a short read, or if not we have all the data.
4915 : */
4916 154472 : goto got_full;
4917 : }
4918 :
4919 : /*
4920 : * Now we analyze the NBT header
4921 : */
4922 154472 : if (state->hdr.nbt[0] != 0x00) {
4923 0 : state->min_recv_size = 0;
4924 : }
4925 154472 : state->pktfull = smb2_len(state->hdr.nbt);
4926 154472 : if (state->pktfull == 0) {
4927 0 : goto got_full;
4928 : }
4929 :
4930 154472 : if (state->min_recv_size != 0) {
4931 0 : min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4932 0 : min_recvfile_size += state->min_recv_size;
4933 : }
4934 :
4935 154472 : if (state->pktfull > min_recvfile_size) {
4936 : /*
4937 : * Might be a receivefile write. Read the SMB2 HEADER +
4938 : * SMB2_WRITE header first. Set 'doing_receivefile'
4939 : * as we're *attempting* receivefile write. If this
4940 : * turns out not to be a SMB2_WRITE request or otherwise
4941 : * not suitable then we'll just read the rest of the data
4942 : * the next time this function is called.
4943 : */
4944 0 : state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
4945 0 : state->doing_receivefile = true;
4946 : } else {
4947 154472 : state->pktlen = state->pktfull;
4948 : }
4949 :
4950 154472 : state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
4951 154472 : if (state->pktbuf == NULL) {
4952 0 : return NT_STATUS_NO_MEMORY;
4953 : }
4954 :
4955 154472 : state->vector.iov_base = (void *)state->pktbuf;
4956 154472 : state->vector.iov_len = state->pktlen;
4957 :
4958 154472 : goto again;
4959 :
4960 154472 : got_full:
4961 :
4962 154472 : if (state->hdr.nbt[0] != 0x00) {
4963 0 : DEBUG(1,("ignore NBT[0x%02X] msg\n",
4964 : state->hdr.nbt[0]));
4965 :
4966 0 : req = state->req;
4967 0 : ZERO_STRUCTP(state);
4968 0 : state->req = req;
4969 0 : state->min_recv_size = lp_min_receive_file_size();
4970 0 : req = NULL;
4971 0 : goto again;
4972 : }
4973 :
4974 154472 : req = state->req;
4975 154472 : state->req = NULL;
4976 :
4977 154472 : req->request_time = timeval_current();
4978 154472 : now = timeval_to_nttime(&req->request_time);
4979 :
4980 154472 : status = smbd_smb2_inbuf_parse_compound(xconn,
4981 : now,
4982 : state->pktbuf,
4983 : state->pktlen,
4984 : req,
4985 : &req->in.vector,
4986 : &req->in.vector_count);
4987 154472 : if (!NT_STATUS_IS_OK(status)) {
4988 0 : return status;
4989 : }
4990 :
4991 154472 : if (state->doing_receivefile) {
4992 0 : req->smb1req = talloc_zero(req, struct smb_request);
4993 0 : if (req->smb1req == NULL) {
4994 0 : return NT_STATUS_NO_MEMORY;
4995 : }
4996 0 : req->smb1req->unread_bytes = state->pktfull - state->pktlen;
4997 : }
4998 :
4999 154472 : ZERO_STRUCTP(state);
5000 :
5001 154472 : req->current_idx = 1;
5002 :
5003 154472 : DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
5004 : req->current_idx, req->in.vector_count));
5005 :
5006 154472 : status = smbd_smb2_request_validate(req);
5007 154472 : if (!NT_STATUS_IS_OK(status)) {
5008 0 : return status;
5009 : }
5010 :
5011 154472 : status = smbd_smb2_request_setup_out(req);
5012 154472 : if (!NT_STATUS_IS_OK(status)) {
5013 0 : return status;
5014 : }
5015 :
5016 154472 : status = smbd_smb2_request_dispatch(req);
5017 152044 : if (!NT_STATUS_IS_OK(status)) {
5018 0 : return status;
5019 : }
5020 :
5021 152044 : sconn->num_requests++;
5022 :
5023 : /* The timeout_processing function isn't run nearly
5024 : often enough to implement 'max log size' without
5025 : overrunning the size of the file by many megabytes.
5026 : This is especially true if we are running at debug
5027 : level 10. Checking every 50 SMB2s is a nice
5028 : tradeoff of performance vs log file size overrun. */
5029 :
5030 153767 : if ((sconn->num_requests % 50) == 0 &&
5031 1723 : need_to_check_log_size()) {
5032 354 : change_to_root_user();
5033 354 : check_log_size();
5034 : }
5035 :
5036 152044 : status = smbd_smb2_request_next_incoming(xconn);
5037 152044 : if (!NT_STATUS_IS_OK(status)) {
5038 0 : return status;
5039 : }
5040 :
5041 152044 : return NT_STATUS_OK;
5042 : }
5043 :
5044 345818 : static void smbd_smb2_connection_handler(struct tevent_context *ev,
5045 : struct tevent_fd *fde,
5046 : uint16_t flags,
5047 : void *private_data)
5048 : {
5049 : struct smbXsrv_connection *xconn =
5050 345818 : talloc_get_type_abort(private_data,
5051 : struct smbXsrv_connection);
5052 : NTSTATUS status;
5053 :
5054 345818 : status = smbd_smb2_io_handler(xconn, flags);
5055 343390 : if (!NT_STATUS_IS_OK(status)) {
5056 2553 : smbd_server_connection_terminate(xconn, nt_errstr(status));
5057 50 : return;
5058 : }
5059 : }
|