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