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