Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Files[] structure handling
4 : Copyright (C) Andrew Tridgell 1998
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "smbd/smbd.h"
22 : #include "smbd/globals.h"
23 : #include "smbd/smbXsrv_open.h"
24 : #include "libcli/security/security.h"
25 : #include "util_tdb.h"
26 : #include "lib/util/bitmap.h"
27 : #include "lib/util/strv.h"
28 : #include "lib/util/memcache.h"
29 : #include "libcli/smb/reparse.h"
30 :
31 : #define FILE_HANDLE_OFFSET 0x1000
32 :
33 : static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
34 : struct smb_filename **_smb_fname);
35 :
36 : /**
37 : * create new fsp to be used for file_new or a durable handle reconnect
38 : */
39 6284198 : NTSTATUS fsp_new(struct connection_struct *conn, TALLOC_CTX *mem_ctx,
40 : files_struct **result)
41 : {
42 6284198 : NTSTATUS status = NT_STATUS_NO_MEMORY;
43 6284198 : files_struct *fsp = NULL;
44 6284198 : struct smbd_server_connection *sconn = conn->sconn;
45 :
46 6284198 : fsp = talloc_zero(mem_ctx, struct files_struct);
47 6284198 : if (fsp == NULL) {
48 0 : goto fail;
49 : }
50 :
51 : /*
52 : * This can't be a child of fsp because the file_handle can be ref'd
53 : * when doing a dos/fcb open, which will then share the file_handle
54 : * across multiple fsps.
55 : */
56 6284198 : fsp->fh = fd_handle_create(mem_ctx);
57 6284198 : if (fsp->fh == NULL) {
58 0 : goto fail;
59 : }
60 :
61 6284198 : fsp->fsp_flags.use_ofd_locks = !lp_smbd_force_process_locks(SNUM(conn));
62 : #ifndef HAVE_OFD_LOCKS
63 : fsp->fsp_flags.use_ofd_locks = false;
64 : #endif
65 :
66 6284198 : fh_set_refcount(fsp->fh, 1);
67 6284198 : fsp_set_fd(fsp, -1);
68 :
69 6284198 : fsp->fnum = FNUM_FIELD_INVALID;
70 6284198 : fsp->conn = conn;
71 6284198 : fsp->close_write_time = make_omit_timespec();
72 :
73 6284198 : DLIST_ADD(sconn->files, fsp);
74 6284198 : sconn->num_files += 1;
75 :
76 6284198 : conn->num_files_open++;
77 :
78 6284198 : DBG_INFO("allocated files structure (%u used)\n",
79 : (unsigned int)sconn->num_files);
80 :
81 6284198 : *result = fsp;
82 6284198 : return NT_STATUS_OK;
83 :
84 0 : fail:
85 0 : if (fsp != NULL) {
86 0 : TALLOC_FREE(fsp->fh);
87 : }
88 0 : TALLOC_FREE(fsp);
89 :
90 0 : return status;
91 : }
92 :
93 6134432 : void fsp_set_gen_id(files_struct *fsp)
94 : {
95 32282 : static uint64_t gen_id = 1;
96 :
97 : /*
98 : * A billion of 64-bit increments per second gives us
99 : * more than 500 years of runtime without wrap.
100 : */
101 6134432 : gen_id++;
102 6134432 : fh_set_gen_id(fsp->fh, gen_id);
103 6134432 : }
104 :
105 : /****************************************************************************
106 : Find first available file slot.
107 : ****************************************************************************/
108 :
109 875171 : NTSTATUS fsp_bind_smb(struct files_struct *fsp, struct smb_request *req)
110 : {
111 875171 : struct smbXsrv_open *op = NULL;
112 3078 : NTTIME now;
113 3078 : NTSTATUS status;
114 :
115 875171 : if (req == NULL) {
116 307192 : DBG_DEBUG("INTERNAL_OPEN_ONLY, skipping smbXsrv_open\n");
117 307192 : return NT_STATUS_OK;
118 : }
119 :
120 567979 : now = timeval_to_nttime(&fsp->open_time);
121 :
122 567979 : status = smbXsrv_open_create(req->xconn,
123 567979 : fsp->conn->session_info,
124 : now,
125 : &op);
126 567979 : if (!NT_STATUS_IS_OK(status)) {
127 2 : return status;
128 : }
129 567977 : fsp->op = op;
130 567977 : op->compat = fsp;
131 567977 : fsp->fnum = op->local_id;
132 :
133 567977 : fsp->mid = req->mid;
134 567977 : req->chain_fsp = fsp;
135 :
136 567977 : DBG_DEBUG("fsp [%s] mid [%" PRIu64"]\n",
137 : fsp_str_dbg(fsp), fsp->mid);
138 :
139 567977 : return NT_STATUS_OK;
140 : }
141 :
142 583696 : NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
143 : files_struct **result)
144 : {
145 583696 : struct smbd_server_connection *sconn = conn->sconn;
146 2129 : files_struct *fsp;
147 2129 : NTSTATUS status;
148 :
149 583696 : status = fsp_new(conn, conn, &fsp);
150 583696 : if (!NT_STATUS_IS_OK(status)) {
151 0 : return status;
152 : }
153 :
154 583696 : GetTimeOfDay(&fsp->open_time);
155 :
156 583696 : status = fsp_bind_smb(fsp, req);
157 583696 : if (!NT_STATUS_IS_OK(status)) {
158 2 : file_free(NULL, fsp);
159 2 : return status;
160 : }
161 :
162 583694 : fsp_set_gen_id(fsp);
163 :
164 : /*
165 : * Create an smb_filename with "" for the base_name. There are very
166 : * few NULL checks, so make sure it's initialized with something. to
167 : * be safe until an audit can be done.
168 : */
169 583694 : fsp->fsp_name = synthetic_smb_fname(fsp,
170 : "",
171 : NULL,
172 : NULL,
173 : 0,
174 : 0);
175 583694 : if (fsp->fsp_name == NULL) {
176 0 : file_free(NULL, fsp);
177 0 : return NT_STATUS_NO_MEMORY;
178 : }
179 :
180 583694 : DBG_INFO("new file %s\n", fsp_fnum_dbg(fsp));
181 :
182 : /* A new fsp invalidates the positive and
183 : negative fsp_fi_cache as the new fsp is pushed
184 : at the start of the list and we search from
185 : a cache hit to the *end* of the list. */
186 :
187 583694 : ZERO_STRUCT(sconn->fsp_fi_cache);
188 :
189 583694 : *result = fsp;
190 583694 : return NT_STATUS_OK;
191 : }
192 :
193 298790 : NTSTATUS create_internal_fsp(connection_struct *conn,
194 : const struct smb_filename *smb_fname,
195 : struct files_struct **_fsp)
196 : {
197 298790 : struct files_struct *fsp = NULL;
198 957 : NTSTATUS status;
199 :
200 298790 : status = file_new(NULL, conn, &fsp);
201 298790 : if (!NT_STATUS_IS_OK(status)) {
202 0 : return status;
203 : }
204 :
205 298790 : status = fsp_set_smb_fname(fsp, smb_fname);
206 298790 : if (!NT_STATUS_IS_OK(status)) {
207 0 : file_free(NULL, fsp);
208 0 : return status;
209 : }
210 :
211 298790 : *_fsp = fsp;
212 298790 : return NT_STATUS_OK;
213 : }
214 :
215 : /*
216 : * Create an internal fsp for an *existing* directory.
217 : *
218 : * This should only be used by callers in the VFS that need to control the
219 : * opening of the directory. Otherwise use open_internal_dirfsp().
220 : */
221 289576 : NTSTATUS create_internal_dirfsp(connection_struct *conn,
222 : const struct smb_filename *smb_dname,
223 : struct files_struct **_fsp)
224 : {
225 289576 : struct files_struct *fsp = NULL;
226 957 : NTSTATUS status;
227 :
228 289576 : status = create_internal_fsp(conn, smb_dname, &fsp);
229 289576 : if (!NT_STATUS_IS_OK(status)) {
230 0 : return status;
231 : }
232 :
233 289576 : fsp->access_mask = FILE_LIST_DIRECTORY;
234 289576 : fsp->fsp_flags.is_directory = true;
235 289576 : fsp->fsp_flags.is_dirfsp = true;
236 :
237 289576 : *_fsp = fsp;
238 289576 : return NT_STATUS_OK;
239 : }
240 :
241 : /*
242 : * Open an internal fsp for an *existing* directory.
243 : */
244 13167 : NTSTATUS open_internal_dirfsp(connection_struct *conn,
245 : const struct smb_filename *smb_dname,
246 : int _open_flags,
247 : struct files_struct **_fsp)
248 : {
249 13167 : struct vfs_open_how how = { .flags = _open_flags, };
250 13167 : struct files_struct *fsp = NULL;
251 74 : NTSTATUS status;
252 :
253 13167 : status = create_internal_dirfsp(conn, smb_dname, &fsp);
254 13167 : if (!NT_STATUS_IS_OK(status)) {
255 0 : return status;
256 : }
257 :
258 : #ifdef O_DIRECTORY
259 13167 : how.flags |= O_DIRECTORY;
260 : #endif
261 13167 : status = fd_openat(conn->cwd_fsp, fsp->fsp_name, fsp, &how);
262 13167 : if (!NT_STATUS_IS_OK(status)) {
263 0 : DBG_INFO("Could not open fd for %s (%s)\n",
264 : smb_fname_str_dbg(smb_dname),
265 : nt_errstr(status));
266 0 : file_free(NULL, fsp);
267 0 : return status;
268 : }
269 :
270 13167 : status = vfs_stat_fsp(fsp);
271 13167 : if (!NT_STATUS_IS_OK(status)) {
272 0 : file_free(NULL, fsp);
273 0 : return status;
274 : }
275 :
276 13167 : if (!S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
277 0 : DBG_ERR("%s is not a directory!\n",
278 : smb_fname_str_dbg(smb_dname));
279 0 : file_free(NULL, fsp);
280 0 : return NT_STATUS_NOT_A_DIRECTORY;
281 : }
282 :
283 13167 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
284 :
285 13167 : *_fsp = fsp;
286 13167 : return NT_STATUS_OK;
287 : }
288 :
289 : /*
290 : * Convert a pathref dirfsp into a real fsp. No need to do any cwd
291 : * tricks, we just open ".".
292 : */
293 273549 : NTSTATUS openat_internal_dir_from_pathref(
294 : struct files_struct *dirfsp,
295 : int _open_flags,
296 : struct files_struct **_fsp)
297 : {
298 273549 : struct connection_struct *conn = dirfsp->conn;
299 273549 : struct smb_filename *smb_dname = dirfsp->fsp_name;
300 273549 : struct files_struct *fsp = NULL;
301 273549 : char dot[] = ".";
302 273549 : struct smb_filename smb_dot = {
303 : .base_name = dot,
304 273549 : .flags = smb_dname->flags,
305 273549 : .twrp = smb_dname->twrp,
306 : };
307 273549 : struct vfs_open_how how = { .flags = _open_flags, };
308 883 : NTSTATUS status;
309 :
310 273549 : status = create_internal_dirfsp(conn, smb_dname, &fsp);
311 273549 : if (!NT_STATUS_IS_OK(status)) {
312 0 : return status;
313 : }
314 :
315 : /*
316 : * Pointless for opening ".", but you never know...
317 : */
318 273549 : how.flags |= O_NOFOLLOW;
319 :
320 273549 : status = fd_openat(dirfsp, &smb_dot, fsp, &how);
321 273549 : if (!NT_STATUS_IS_OK(status)) {
322 1 : DBG_INFO("fd_openat(\"%s\", \".\") failed: %s\n",
323 : fsp_str_dbg(dirfsp),
324 : nt_errstr(status));
325 1 : file_free(NULL, fsp);
326 1 : return status;
327 : }
328 :
329 273548 : fsp->fsp_name->st = smb_dname->st;
330 273548 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
331 273548 : *_fsp = fsp;
332 273548 : return NT_STATUS_OK;
333 : }
334 :
335 : /*
336 : * The "link" in the name doesn't imply link in the filesystem
337 : * sense. It's a object that "links" together an fsp and an smb_fname
338 : * and the link allocated as talloc child of an fsp.
339 : *
340 : * The link is created for fsps that openat_pathref_fsp() returns in
341 : * smb_fname->fsp. When this fsp is freed by file_free() by some caller
342 : * somewhere, the destructor fsp_smb_fname_link_destructor() on the link object
343 : * will use the link to reset the reference in smb_fname->fsp that is about to
344 : * go away.
345 : *
346 : * This prevents smb_fname_internal_fsp_destructor() from seeing dangling fsp
347 : * pointers.
348 : */
349 :
350 : struct fsp_smb_fname_link {
351 : struct fsp_smb_fname_link **smb_fname_link;
352 : struct files_struct **smb_fname_fsp;
353 : };
354 :
355 6083805 : static int fsp_smb_fname_link_destructor(struct fsp_smb_fname_link *link)
356 : {
357 6083805 : if (link->smb_fname_link == NULL) {
358 0 : return 0;
359 : }
360 :
361 6083805 : *link->smb_fname_link = NULL;
362 6083805 : *link->smb_fname_fsp = NULL;
363 6083805 : return 0;
364 : }
365 :
366 10305371 : static NTSTATUS fsp_smb_fname_link(struct files_struct *fsp,
367 : struct fsp_smb_fname_link **smb_fname_link,
368 : struct files_struct **smb_fname_fsp)
369 : {
370 10305371 : struct fsp_smb_fname_link *link = NULL;
371 :
372 10305371 : SMB_ASSERT(*smb_fname_link == NULL);
373 10305371 : SMB_ASSERT(*smb_fname_fsp == NULL);
374 :
375 10305371 : link = talloc_zero(fsp, struct fsp_smb_fname_link);
376 10305371 : if (link == NULL) {
377 0 : return NT_STATUS_NO_MEMORY;
378 : }
379 :
380 10305371 : link->smb_fname_link = smb_fname_link;
381 10305371 : link->smb_fname_fsp = smb_fname_fsp;
382 10305371 : *smb_fname_link = link;
383 10305371 : *smb_fname_fsp = fsp;
384 :
385 10305371 : talloc_set_destructor(link, fsp_smb_fname_link_destructor);
386 10305371 : return NT_STATUS_OK;
387 : }
388 :
389 : /*
390 : * Free a link, carefully avoiding to trigger the link destructor
391 : */
392 5437693 : static void destroy_fsp_smb_fname_link(struct fsp_smb_fname_link **_link)
393 : {
394 5437693 : struct fsp_smb_fname_link *link = *_link;
395 :
396 5437693 : if (link == NULL) {
397 1203612 : return;
398 : }
399 4221546 : talloc_set_destructor(link, NULL);
400 4221546 : TALLOC_FREE(link);
401 4221546 : *_link = NULL;
402 : }
403 :
404 : /*
405 : * Talloc destructor set on an smb_fname set by openat_pathref_fsp() used to
406 : * close the embedded smb_fname->fsp.
407 : */
408 3400219 : static int smb_fname_fsp_destructor(struct smb_filename *smb_fname)
409 : {
410 3400219 : struct files_struct *fsp = smb_fname->fsp;
411 3400219 : struct files_struct *base_fsp = NULL;
412 23276 : NTSTATUS status;
413 3400219 : int saved_errno = errno;
414 :
415 3400219 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
416 :
417 3400219 : if (fsp == NULL) {
418 8824 : errno = saved_errno;
419 8824 : return 0;
420 : }
421 :
422 3391395 : if (fsp_is_alternate_stream(fsp)) {
423 775 : base_fsp = fsp->base_fsp;
424 : }
425 :
426 3391395 : status = fd_close(fsp);
427 3391395 : if (!NT_STATUS_IS_OK(status)) {
428 0 : DBG_ERR("Closing fd for fsp [%s] failed: %s. "
429 : "Please check your filesystem!!!\n",
430 : fsp_str_dbg(fsp), nt_errstr(status));
431 : }
432 3391395 : file_free(NULL, fsp);
433 3391395 : smb_fname->fsp = NULL;
434 :
435 3391395 : if (base_fsp != NULL) {
436 775 : base_fsp->stream_fsp = NULL;
437 775 : status = fd_close(base_fsp);
438 775 : if (!NT_STATUS_IS_OK(status)) {
439 0 : DBG_ERR("Closing fd for base_fsp [%s] failed: %s. "
440 : "Please check your filesystem!!!\n",
441 : fsp_str_dbg(base_fsp), nt_errstr(status));
442 : }
443 775 : file_free(NULL, base_fsp);
444 : }
445 :
446 3391395 : errno = saved_errno;
447 3391395 : return 0;
448 : }
449 :
450 3422577 : static NTSTATUS openat_pathref_fullname(
451 : struct connection_struct *conn,
452 : const struct files_struct *dirfsp,
453 : struct files_struct *basefsp,
454 : struct smb_filename **full_fname,
455 : struct smb_filename *smb_fname,
456 : const struct vfs_open_how *how)
457 : {
458 3422577 : struct files_struct *fsp = NULL;
459 3422577 : bool have_dirfsp = (dirfsp != NULL);
460 3422577 : bool have_basefsp = (basefsp != NULL);
461 10525 : NTSTATUS status;
462 :
463 3422577 : DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
464 :
465 3422577 : SMB_ASSERT(smb_fname->fsp == NULL);
466 3422577 : SMB_ASSERT(have_dirfsp != have_basefsp);
467 :
468 3422577 : status = fsp_new(conn, conn, &fsp);
469 3422577 : if (!NT_STATUS_IS_OK(status)) {
470 0 : return status;
471 : }
472 :
473 3422577 : GetTimeOfDay(&fsp->open_time);
474 3422577 : fsp_set_gen_id(fsp);
475 3422577 : ZERO_STRUCT(conn->sconn->fsp_fi_cache);
476 :
477 3422577 : fsp->fsp_flags.is_pathref = true;
478 :
479 3422577 : status = fsp_attach_smb_fname(fsp, full_fname);
480 3422577 : if (!NT_STATUS_IS_OK(status)) {
481 0 : goto fail;
482 : }
483 3422577 : fsp_set_base_fsp(fsp, basefsp);
484 :
485 3422577 : status = fd_openat(dirfsp, smb_fname, fsp, how);
486 3422577 : if (!NT_STATUS_IS_OK(status)) {
487 :
488 1516978 : smb_fname->st = fsp->fsp_name->st;
489 :
490 1516978 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) ||
491 1515552 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
492 1510486 : NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK))
493 : {
494 : /*
495 : * streams_xattr return NT_STATUS_NOT_FOUND for
496 : * opens of not yet existing streams.
497 : *
498 : * ELOOP maps to NT_STATUS_OBJECT_PATH_NOT_FOUND
499 : * and this will result from a open request from
500 : * a POSIX client on a symlink.
501 : *
502 : * NT_STATUS_OBJECT_NAME_NOT_FOUND is the simple
503 : * ENOENT case.
504 : *
505 : * NT_STATUS_STOPPED_ON_SYMLINK is returned when trying
506 : * to open a symlink, our callers are not interested in
507 : * this.
508 : */
509 1447 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
510 : }
511 1516978 : goto fail;
512 : }
513 :
514 : /*
515 : * fd_openat() has done an FSTAT on the handle
516 : * so update the smb_fname stat info with "truth".
517 : * from the handle.
518 : */
519 1905599 : smb_fname->st = fsp->fsp_name->st;
520 :
521 1905599 : fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
522 :
523 1905599 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
524 :
525 1905599 : status = fsp_smb_fname_link(fsp,
526 : &smb_fname->fsp_link,
527 : &smb_fname->fsp);
528 1905599 : if (!NT_STATUS_IS_OK(status)) {
529 0 : goto fail;
530 : }
531 :
532 1905599 : DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp));
533 :
534 1905599 : talloc_set_destructor(smb_fname, smb_fname_fsp_destructor);
535 1905599 : return NT_STATUS_OK;
536 :
537 1516978 : fail:
538 1516978 : DBG_DEBUG("Opening pathref for [%s] failed: %s\n",
539 : smb_fname_str_dbg(smb_fname),
540 : nt_errstr(status));
541 :
542 1516978 : fsp_set_base_fsp(fsp, NULL);
543 1516978 : fd_close(fsp);
544 1516978 : file_free(NULL, fsp);
545 1516978 : return status;
546 : }
547 :
548 : /*
549 : * Open an internal O_PATH based fsp for smb_fname. If O_PATH is not
550 : * available, open O_RDONLY as root. Both is done in fd_open() ->
551 : * non_widelink_open(), triggered by setting fsp->fsp_flags.is_pathref to
552 : * true.
553 : */
554 3414822 : NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
555 : struct smb_filename *smb_fname)
556 : {
557 3414822 : connection_struct *conn = dirfsp->conn;
558 3414822 : struct smb_filename *full_fname = NULL;
559 3414822 : struct smb_filename *base_fname = NULL;
560 3414822 : struct vfs_open_how how = { .flags = O_RDONLY|O_NONBLOCK, };
561 10543 : NTSTATUS status;
562 :
563 3414822 : DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
564 :
565 3414822 : if (smb_fname->fsp != NULL) {
566 : /* We already have one for this name. */
567 450 : DBG_DEBUG("smb_fname [%s] already has a pathref fsp.\n",
568 : smb_fname_str_dbg(smb_fname));
569 450 : return NT_STATUS_OK;
570 : }
571 :
572 3414372 : if (is_named_stream(smb_fname) &&
573 1977 : ((conn->fs_capabilities & FILE_NAMED_STREAMS) == 0)) {
574 0 : DBG_DEBUG("stream open [%s] on non-stream share\n",
575 : smb_fname_str_dbg(smb_fname));
576 0 : return NT_STATUS_OBJECT_NAME_INVALID;
577 : }
578 :
579 3414372 : if (!is_named_stream(smb_fname)) {
580 : /*
581 : * openat_pathref_fullname() will make "full_fname" a
582 : * talloc child of the smb_fname->fsp. Don't use
583 : * talloc_tos() to allocate it to avoid making the
584 : * talloc stackframe pool long-lived.
585 : */
586 3412395 : full_fname = full_path_from_dirfsp_atname(
587 : conn,
588 : dirfsp,
589 : smb_fname);
590 3412395 : if (full_fname == NULL) {
591 0 : status = NT_STATUS_NO_MEMORY;
592 0 : goto fail;
593 : }
594 3412395 : status = openat_pathref_fullname(
595 : conn, dirfsp, NULL, &full_fname, smb_fname, &how);
596 3412395 : TALLOC_FREE(full_fname);
597 3412395 : return status;
598 : }
599 :
600 : /*
601 : * stream open
602 : */
603 1977 : base_fname = cp_smb_filename_nostream(conn, smb_fname);
604 1977 : if (base_fname == NULL) {
605 0 : return NT_STATUS_NO_MEMORY;
606 : }
607 :
608 1977 : full_fname = full_path_from_dirfsp_atname(
609 : conn, /* no talloc_tos(), see comment above */
610 : dirfsp,
611 : base_fname);
612 1977 : if (full_fname == NULL) {
613 0 : status = NT_STATUS_NO_MEMORY;
614 0 : goto fail;
615 : }
616 :
617 1977 : status = openat_pathref_fullname(
618 : conn, dirfsp, NULL, &full_fname, base_fname, &how);
619 1977 : TALLOC_FREE(full_fname);
620 1977 : if (!NT_STATUS_IS_OK(status)) {
621 0 : DBG_DEBUG("openat_pathref_fullname() failed: %s\n",
622 : nt_errstr(status));
623 0 : goto fail;
624 : }
625 :
626 1977 : status = open_stream_pathref_fsp(&base_fname->fsp, smb_fname);
627 1977 : if (!NT_STATUS_IS_OK(status)) {
628 282 : DBG_DEBUG("open_stream_pathref_fsp failed: %s\n",
629 : nt_errstr(status));
630 282 : goto fail;
631 : }
632 :
633 1695 : smb_fname_fsp_unlink(base_fname);
634 1977 : fail:
635 1977 : TALLOC_FREE(base_fname);
636 1977 : return status;
637 : }
638 :
639 : /*
640 : * Open a stream given an already opened base_fsp. Avoid
641 : * non_widelink_open: This is only valid for the case where we have a
642 : * valid non-cwd_fsp dirfsp that we can pass to SMB_VFS_OPENAT()
643 : */
644 8205 : NTSTATUS open_stream_pathref_fsp(
645 : struct files_struct **_base_fsp,
646 : struct smb_filename *smb_fname)
647 : {
648 8205 : struct files_struct *base_fsp = *_base_fsp;
649 8205 : connection_struct *conn = base_fsp->conn;
650 8205 : struct smb_filename *base_fname = base_fsp->fsp_name;
651 8205 : struct smb_filename *full_fname = NULL;
652 8205 : struct vfs_open_how how = { .flags = O_RDONLY|O_NONBLOCK, };
653 4 : NTSTATUS status;
654 :
655 8205 : SMB_ASSERT(smb_fname->fsp == NULL);
656 8205 : SMB_ASSERT(is_named_stream(smb_fname));
657 :
658 16410 : full_fname = synthetic_smb_fname(
659 : conn, /* no talloc_tos(), this will be long-lived */
660 8205 : base_fname->base_name,
661 8205 : smb_fname->stream_name,
662 8205 : &smb_fname->st,
663 : smb_fname->twrp,
664 : smb_fname->flags);
665 8205 : if (full_fname == NULL) {
666 0 : return NT_STATUS_NO_MEMORY;
667 : }
668 :
669 8205 : status = openat_pathref_fullname(
670 : conn, NULL, base_fsp, &full_fname, smb_fname, &how);
671 8205 : TALLOC_FREE(full_fname);
672 8205 : return status;
673 : }
674 :
675 570963 : static char *path_to_strv(TALLOC_CTX *mem_ctx, const char *path)
676 : {
677 570963 : char *result = talloc_strdup(mem_ctx, path);
678 :
679 570963 : if (result == NULL) {
680 0 : return NULL;
681 : }
682 570963 : string_replace(result, '/', '\0');
683 570963 : return result;
684 : }
685 :
686 73959 : NTSTATUS readlink_talloc(
687 : TALLOC_CTX *mem_ctx,
688 : struct files_struct *dirfsp,
689 : struct smb_filename *smb_relname,
690 : char **_substitute)
691 : {
692 73959 : struct smb_filename null_fname = {
693 : .base_name = discard_const_p(char, ""),
694 : };
695 0 : char buf[PATH_MAX];
696 0 : ssize_t ret;
697 0 : char *substitute;
698 0 : NTSTATUS status;
699 :
700 73959 : if (smb_relname == NULL) {
701 : /*
702 : * We have a Linux O_PATH handle in dirfsp and want to
703 : * read its value, essentially a freadlink
704 : */
705 38671 : smb_relname = &null_fname;
706 : }
707 :
708 73959 : ret = SMB_VFS_READLINKAT(
709 : dirfsp->conn, dirfsp, smb_relname, buf, sizeof(buf));
710 73959 : if (ret < 0) {
711 16 : status = map_nt_error_from_unix(errno);
712 16 : DBG_DEBUG("SMB_VFS_READLINKAT() failed: %s\n",
713 : strerror(errno));
714 16 : return status;
715 : }
716 :
717 73943 : if ((size_t)ret == sizeof(buf)) {
718 : /*
719 : * Do we need symlink targets longer than PATH_MAX?
720 : */
721 0 : DBG_DEBUG("Got full %zu bytes from readlink, too long\n",
722 : sizeof(buf));
723 0 : return NT_STATUS_BUFFER_OVERFLOW;
724 : }
725 :
726 73943 : substitute = talloc_strndup(mem_ctx, buf, ret);
727 73943 : if (substitute == NULL) {
728 0 : DBG_DEBUG("talloc_strndup() failed\n");
729 0 : return NT_STATUS_NO_MEMORY;
730 : }
731 :
732 73943 : *_substitute = substitute;
733 73943 : return NT_STATUS_OK;
734 : }
735 :
736 71598 : NTSTATUS read_symlink_reparse(TALLOC_CTX *mem_ctx,
737 : struct files_struct *dirfsp,
738 : struct smb_filename *smb_relname,
739 : struct reparse_data_buffer **_reparse)
740 : {
741 71598 : struct reparse_data_buffer *reparse = NULL;
742 71598 : struct symlink_reparse_struct *lnk = NULL;
743 0 : NTSTATUS status;
744 :
745 71598 : reparse = talloc_zero(mem_ctx, struct reparse_data_buffer);
746 71598 : if (reparse == NULL) {
747 0 : goto nomem;
748 : }
749 71598 : *reparse = (struct reparse_data_buffer){
750 : .tag = IO_REPARSE_TAG_SYMLINK,
751 : };
752 71598 : lnk = &reparse->parsed.lnk;
753 :
754 71598 : status = readlink_talloc(reparse,
755 : dirfsp,
756 : smb_relname,
757 : &lnk->substitute_name);
758 71598 : if (!NT_STATUS_IS_OK(status)) {
759 16 : DBG_DEBUG("readlink_talloc failed: %s\n", nt_errstr(status));
760 16 : goto fail;
761 : }
762 :
763 71582 : if (lnk->substitute_name[0] == '/') {
764 18744 : char *subdir_path = NULL;
765 18744 : char *abs_target_canon = NULL;
766 18744 : const char *relative = NULL;
767 0 : bool in_share;
768 :
769 18744 : subdir_path = talloc_asprintf(talloc_tos(),
770 : "%s/%s",
771 18744 : dirfsp->conn->connectpath,
772 18744 : dirfsp->fsp_name->base_name);
773 18744 : if (subdir_path == NULL) {
774 0 : goto nomem;
775 : }
776 :
777 18744 : abs_target_canon = canonicalize_absolute_path(
778 18744 : talloc_tos(), lnk->substitute_name);
779 18744 : if (abs_target_canon == NULL) {
780 0 : goto nomem;
781 : }
782 :
783 18744 : in_share = subdir_of(subdir_path,
784 : strlen(subdir_path),
785 : abs_target_canon,
786 : &relative);
787 18744 : if (in_share) {
788 7484 : TALLOC_FREE(lnk->substitute_name);
789 7484 : lnk->substitute_name = talloc_strdup(reparse,
790 : relative);
791 7484 : if (lnk->substitute_name == NULL) {
792 0 : goto nomem;
793 : }
794 : }
795 : }
796 :
797 71582 : if (!IS_DIRECTORY_SEP(lnk->substitute_name[0])) {
798 60322 : lnk->flags |= SYMLINK_FLAG_RELATIVE;
799 : }
800 :
801 71582 : *_reparse = reparse;
802 71582 : return NT_STATUS_OK;
803 0 : nomem:
804 0 : status = NT_STATUS_NO_MEMORY;
805 16 : fail:
806 16 : TALLOC_FREE(reparse);
807 16 : return status;
808 : }
809 :
810 682643 : static bool full_path_extend(char **dir, const char *atname)
811 : {
812 682643 : talloc_asprintf_addbuf(dir,
813 : "%s%s",
814 682643 : (*dir)[0] == '\0' ? "" : "/",
815 : atname);
816 682643 : return (*dir) != NULL;
817 : }
818 :
819 : /*
820 : * Create the memcache-key for GETREALFILENAME_CACHE: This supplements
821 : * the stat cache for the last component to be looked up. Cache
822 : * contents is the correctly capitalized translation of the parameter
823 : * "name" as it exists on disk. This is indexed by inode of the dirfsp
824 : * and name, and contrary to stat_cahce_lookup() it does not
825 : * vfs_stat() the last component. This will be taken care of by an
826 : * attempt to do a openat_pathref_fsp().
827 : */
828 270557 : static bool get_real_filename_cache_key(TALLOC_CTX *mem_ctx,
829 : struct files_struct *dirfsp,
830 : const char *name,
831 : DATA_BLOB *_key)
832 : {
833 270557 : struct file_id fid = vfs_file_id_from_sbuf(dirfsp->conn,
834 270557 : &dirfsp->fsp_name->st);
835 270557 : char *upper = NULL;
836 270557 : uint8_t *key = NULL;
837 885 : size_t namelen, keylen;
838 :
839 270557 : upper = talloc_strdup_upper(mem_ctx, name);
840 270557 : if (upper == NULL) {
841 0 : return false;
842 : }
843 270557 : namelen = talloc_get_size(upper);
844 :
845 270557 : keylen = namelen + sizeof(fid);
846 270557 : if (keylen < sizeof(fid)) {
847 0 : TALLOC_FREE(upper);
848 0 : return false;
849 : }
850 :
851 270557 : key = talloc_size(mem_ctx, keylen);
852 270557 : if (key == NULL) {
853 0 : TALLOC_FREE(upper);
854 0 : return false;
855 : }
856 :
857 270557 : memcpy(key, &fid, sizeof(fid));
858 270557 : memcpy(key + sizeof(fid), upper, namelen);
859 270557 : TALLOC_FREE(upper);
860 :
861 270557 : *_key = (DATA_BLOB){
862 : .data = key,
863 : .length = keylen,
864 : };
865 270557 : return true;
866 : }
867 :
868 2081621 : static int smb_vfs_openat_ci(TALLOC_CTX *mem_ctx,
869 : bool case_sensitive,
870 : struct connection_struct *conn,
871 : struct files_struct *dirfsp,
872 : struct smb_filename *smb_fname_rel,
873 : files_struct *fsp,
874 : const struct vfs_open_how *how)
875 : {
876 2081621 : char *orig_base_name = smb_fname_rel->base_name;
877 2081621 : DATA_BLOB cache_key = {
878 : .data = NULL,
879 : };
880 2081621 : DATA_BLOB cache_value = {
881 : .data = NULL,
882 : };
883 19632 : NTSTATUS status;
884 19632 : int fd;
885 19632 : bool ok;
886 :
887 2081621 : fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname_rel, fsp, how);
888 2081621 : if ((fd >= 0) || case_sensitive) {
889 1730191 : return fd;
890 : }
891 332683 : if (errno != ENOENT) {
892 62126 : return -1;
893 : }
894 :
895 270557 : if (!lp_stat_cache()) {
896 0 : goto lookup;
897 : }
898 :
899 270557 : ok = get_real_filename_cache_key(mem_ctx,
900 : dirfsp,
901 : orig_base_name,
902 : &cache_key);
903 270557 : if (!ok) {
904 : /*
905 : * probably ENOMEM, just bail
906 : */
907 0 : errno = ENOMEM;
908 0 : return -1;
909 : }
910 :
911 270557 : DO_PROFILE_INC(statcache_lookups);
912 :
913 270557 : ok = memcache_lookup(NULL,
914 : GETREALFILENAME_CACHE,
915 : cache_key,
916 : &cache_value);
917 270557 : if (!ok) {
918 268588 : DO_PROFILE_INC(statcache_misses);
919 268588 : goto lookup;
920 : }
921 1969 : DO_PROFILE_INC(statcache_hits);
922 :
923 3938 : smb_fname_rel->base_name = talloc_strndup(mem_ctx,
924 1969 : (char *)cache_value.data,
925 : cache_value.length);
926 1969 : if (smb_fname_rel->base_name == NULL) {
927 0 : TALLOC_FREE(cache_key.data);
928 0 : smb_fname_rel->base_name = orig_base_name;
929 0 : errno = ENOMEM;
930 0 : return -1;
931 : }
932 :
933 1969 : if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
934 0 : DBG_DEBUG("veto files rejecting last component %s\n",
935 : smb_fname_str_dbg(smb_fname_rel));
936 0 : TALLOC_FREE(cache_key.data);
937 0 : smb_fname_rel->base_name = orig_base_name;
938 0 : errno = EPERM;
939 0 : return -1;
940 : }
941 :
942 1969 : fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname_rel, fsp, how);
943 1969 : if (fd >= 0) {
944 1892 : TALLOC_FREE(cache_key.data);
945 1892 : return fd;
946 : }
947 :
948 77 : memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
949 :
950 : /*
951 : * For the "new filename" case we need to preserve the
952 : * capitalization the client sent us, see
953 : * https://bugzilla.samba.org/show_bug.cgi?id=15481
954 : */
955 77 : TALLOC_FREE(smb_fname_rel->base_name);
956 77 : smb_fname_rel->base_name = orig_base_name;
957 :
958 268665 : lookup:
959 :
960 268665 : status = get_real_filename_at(dirfsp,
961 : orig_base_name,
962 : mem_ctx,
963 : &smb_fname_rel->base_name);
964 268665 : if (!NT_STATUS_IS_OK(status)) {
965 267060 : DBG_DEBUG("get_real_filename_at() failed: %s\n",
966 : nt_errstr(status));
967 267060 : errno = ENOENT;
968 267060 : return -1;
969 : }
970 :
971 1605 : if (IS_VETO_PATH(conn, smb_fname_rel->base_name)) {
972 24 : DBG_DEBUG("found veto files path component "
973 : "%s => %s\n",
974 : orig_base_name,
975 : smb_fname_rel->base_name);
976 24 : TALLOC_FREE(smb_fname_rel->base_name);
977 24 : smb_fname_rel->base_name = orig_base_name;
978 24 : errno = ENOENT;
979 24 : return -1;
980 : }
981 :
982 1581 : fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname_rel, fsp, how);
983 :
984 1581 : if ((fd >= 0) && (cache_key.data != NULL)) {
985 1497 : DATA_BLOB value = {
986 1497 : .data = (uint8_t *)smb_fname_rel->base_name,
987 1497 : .length = strlen(smb_fname_rel->base_name) + 1,
988 : };
989 :
990 1497 : memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
991 1497 : TALLOC_FREE(cache_key.data);
992 : }
993 :
994 1577 : return fd;
995 : }
996 :
997 570963 : NTSTATUS openat_pathref_fsp_nosymlink(
998 : TALLOC_CTX *mem_ctx,
999 : struct connection_struct *conn,
1000 : struct files_struct *in_dirfsp,
1001 : const char *path_in,
1002 : NTTIME twrp,
1003 : bool posix,
1004 : struct smb_filename **_smb_fname,
1005 : struct reparse_data_buffer **_symlink_err)
1006 : {
1007 570963 : struct files_struct *dirfsp = in_dirfsp;
1008 1141926 : struct smb_filename full_fname = {
1009 : .base_name = NULL,
1010 : .twrp = twrp,
1011 570963 : .flags = posix ? SMB_FILENAME_POSIX_PATH : 0,
1012 : };
1013 570963 : struct smb_filename rel_fname = {
1014 : .base_name = NULL,
1015 : .twrp = twrp,
1016 562054 : .flags = full_fname.flags,
1017 : };
1018 570963 : struct smb_filename *result = NULL;
1019 570963 : struct reparse_data_buffer *symlink_err = NULL;
1020 570963 : struct files_struct *fsp = NULL;
1021 570963 : char *path = NULL, *next = NULL;
1022 8909 : bool ok, is_toplevel;
1023 8909 : int fd;
1024 8909 : NTSTATUS status;
1025 570963 : struct vfs_open_how how = {
1026 : .flags = O_NOFOLLOW | O_NONBLOCK,
1027 : .mode = 0,
1028 : };
1029 :
1030 570963 : DBG_DEBUG("path_in=%s\n", path_in);
1031 :
1032 570963 : status = fsp_new(conn, conn, &fsp);
1033 570963 : if (!NT_STATUS_IS_OK(status)) {
1034 0 : DBG_DEBUG("fsp_new() failed: %s\n", nt_errstr(status));
1035 0 : goto fail;
1036 : }
1037 :
1038 570963 : GetTimeOfDay(&fsp->open_time);
1039 570963 : fsp_set_gen_id(fsp);
1040 570963 : ZERO_STRUCT(conn->sconn->fsp_fi_cache);
1041 :
1042 570963 : fsp->fsp_name = &full_fname;
1043 :
1044 : #ifdef O_PATH
1045 : /*
1046 : * Add O_PATH manually, doing this by setting
1047 : * fsp->fsp_flags.is_pathref will make us become_root() in the
1048 : * non-O_PATH case, which would cause a security problem.
1049 : */
1050 388172 : how.flags |= O_PATH;
1051 : #else
1052 : #ifdef O_SEARCH
1053 : /*
1054 : * O_SEARCH just checks for the "x" bit. We are traversing
1055 : * directories, so we don't need the implicit O_RDONLY ("r"
1056 : * permissions) but only the "x"-permissions requested by
1057 : * O_SEARCH. We need either O_PATH or O_SEARCH to correctly
1058 : * function, without either we will incorrectly require also
1059 : * the "r" bit when traversing the directory hierarchy.
1060 : */
1061 : how.flags |= O_SEARCH;
1062 : #endif
1063 : #endif
1064 :
1065 570963 : is_toplevel = (dirfsp == dirfsp->conn->cwd_fsp);
1066 570963 : is_toplevel |= ISDOT(dirfsp->fsp_name->base_name);
1067 :
1068 579872 : full_fname.base_name =
1069 570963 : talloc_strdup(talloc_tos(),
1070 0 : is_toplevel ? "" : dirfsp->fsp_name->base_name);
1071 570963 : if (full_fname.base_name == NULL) {
1072 0 : DBG_DEBUG("talloc_strdup() failed\n");
1073 0 : goto nomem;
1074 : }
1075 :
1076 : /*
1077 : * First split the path into individual components.
1078 : */
1079 570963 : path = path_to_strv(talloc_tos(), path_in);
1080 570963 : if (path == NULL) {
1081 0 : DBG_DEBUG("path_to_strv() failed\n");
1082 0 : goto nomem;
1083 : }
1084 :
1085 : /*
1086 : * First we loop over all components
1087 : * in order to verify, there's no '.' or '..'
1088 : */
1089 570963 : rel_fname.base_name = path;
1090 2186893 : while (rel_fname.base_name != NULL) {
1091 :
1092 1615948 : next = strv_next(path, rel_fname.base_name);
1093 :
1094 : /*
1095 : * Path sanitizing further up has cleaned or rejected
1096 : * empty path components. Assert this here.
1097 : */
1098 1615948 : SMB_ASSERT(rel_fname.base_name[0] != '\0');
1099 :
1100 1615948 : if (ISDOT(rel_fname.base_name) ||
1101 1607035 : ISDOTDOT(rel_fname.base_name)) {
1102 0 : DBG_DEBUG("%s contains a dot\n", path_in);
1103 0 : status = NT_STATUS_OBJECT_NAME_INVALID;
1104 0 : goto fail;
1105 : }
1106 :
1107 : /* Check veto files. */
1108 1615948 : if (IS_VETO_PATH(conn, rel_fname.base_name)) {
1109 18 : DBG_DEBUG("%s contains veto files path component %s\n",
1110 : path_in, rel_fname.base_name);
1111 18 : status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1112 18 : goto fail;
1113 : }
1114 :
1115 1615930 : rel_fname.base_name = next;
1116 : }
1117 :
1118 570945 : if (conn->open_how_resolve & VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS) {
1119 :
1120 : /*
1121 : * Try a direct openat2 with RESOLVE_NO_SYMLINKS to
1122 : * avoid the openat/close loop further down.
1123 : */
1124 :
1125 261921 : rel_fname.base_name = discard_const_p(char, path_in);
1126 261921 : how.resolve = VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS;
1127 :
1128 261921 : fd = SMB_VFS_OPENAT(conn, dirfsp, &rel_fname, fsp, &how);
1129 261921 : if (fd >= 0) {
1130 217460 : fsp_set_fd(fsp, fd);
1131 217460 : ok = full_path_extend(&full_fname.base_name,
1132 217460 : rel_fname.base_name);
1133 217460 : if (!ok) {
1134 0 : goto nomem;
1135 : }
1136 217460 : goto done;
1137 : }
1138 :
1139 44461 : status = map_nt_error_from_unix(errno);
1140 44461 : DBG_DEBUG("SMB_VFS_OPENAT(%s, %s, RESOLVE_NO_SYMLINKS) "
1141 : "returned %d %s => %s\n",
1142 : smb_fname_str_dbg(dirfsp->fsp_name), path_in,
1143 : errno, strerror(errno), nt_errstr(status));
1144 44461 : SMB_ASSERT(fd == -1);
1145 44461 : switch (errno) {
1146 26165 : case ENOSYS:
1147 : /*
1148 : * We got ENOSYS, so fallback to the old code
1149 : * if the kernel doesn't support openat2() yet.
1150 : */
1151 26165 : break;
1152 :
1153 16945 : case ELOOP:
1154 : case ENOTDIR:
1155 : /*
1156 : * For ELOOP we also fallback in order to
1157 : * return the correct information with
1158 : * NT_STATUS_STOPPED_ON_SYMLINK.
1159 : *
1160 : * O_NOFOLLOW|O_DIRECTORY results in
1161 : * ENOTDIR instead of ELOOP for the final
1162 : * component.
1163 : */
1164 16945 : break;
1165 :
1166 1303 : case ENOENT:
1167 : /*
1168 : * If we got ENOENT, the filesystem could
1169 : * be case sensitive. For now we only do
1170 : * the get_real_filename_at() dance in
1171 : * the fallback loop below.
1172 : */
1173 1303 : break;
1174 :
1175 3 : default:
1176 3 : goto fail;
1177 : }
1178 :
1179 : /*
1180 : * Just fallback to the openat loop
1181 : */
1182 44458 : how.resolve = 0;
1183 : }
1184 :
1185 : /*
1186 : * Now we loop over all components
1187 : * opening each one and using it
1188 : * as dirfd for the next one.
1189 : *
1190 : * It means we can detect symlinks
1191 : * within the path.
1192 : */
1193 353482 : rel_fname.base_name = path;
1194 524561 : next:
1195 524561 : next = strv_next(path, rel_fname.base_name);
1196 :
1197 524561 : fd = smb_vfs_openat_ci(talloc_tos(),
1198 524561 : posix || conn->case_sensitive,
1199 : conn,
1200 : dirfsp,
1201 : &rel_fname,
1202 : fsp,
1203 : &how);
1204 :
1205 : #ifndef O_PATH
1206 253946 : if ((fd == -1) && (errno == ELOOP)) {
1207 : int ret;
1208 :
1209 : /*
1210 : * openat() hit a symlink. With O_PATH we open the
1211 : * symlink and get ENOTDIR in the next round, see
1212 : * below.
1213 : */
1214 :
1215 24798 : status = read_symlink_reparse(mem_ctx,
1216 : dirfsp,
1217 : &rel_fname,
1218 : &symlink_err);
1219 24798 : if (!NT_STATUS_IS_OK(status)) {
1220 0 : DBG_DEBUG("read_symlink_reparse failed: %s\n",
1221 : nt_errstr(status));
1222 0 : goto fail;
1223 : }
1224 :
1225 24798 : if (next != NULL) {
1226 22245 : size_t parsed = next - path;
1227 22245 : size_t len = talloc_get_size(path);
1228 22245 : size_t unparsed = len - parsed;
1229 :
1230 22245 : if (unparsed > UINT16_MAX) {
1231 0 : status = NT_STATUS_BUFFER_OVERFLOW;
1232 0 : goto fail;
1233 : }
1234 22245 : symlink_err->parsed.lnk
1235 22245 : .unparsed_path_length = unparsed;
1236 : }
1237 :
1238 : /*
1239 : * We know rel_fname is a symlink, now fill in the
1240 : * rest of the metadata for our callers.
1241 : */
1242 :
1243 24798 : ret = SMB_VFS_FSTATAT(conn,
1244 : dirfsp,
1245 : &rel_fname,
1246 : &full_fname.st,
1247 : AT_SYMLINK_NOFOLLOW);
1248 24798 : if (ret == -1) {
1249 0 : status = map_nt_error_from_unix(errno);
1250 0 : DBG_DEBUG("SMB_VFS_FSTATAT(%s/%s) failed: %s\n",
1251 : fsp_str_dbg(dirfsp),
1252 : rel_fname.base_name,
1253 : strerror(errno));
1254 0 : TALLOC_FREE(symlink_err);
1255 0 : goto fail;
1256 : }
1257 :
1258 24798 : if (!S_ISLNK(full_fname.st.st_ex_mode)) {
1259 : /*
1260 : * Hit a race: readlink_talloc() worked before
1261 : * the fstatat(), but rel_fname changed to
1262 : * something that's not a symlink.
1263 : */
1264 0 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1265 0 : TALLOC_FREE(symlink_err);
1266 0 : goto fail;
1267 : }
1268 :
1269 24798 : status = NT_STATUS_STOPPED_ON_SYMLINK;
1270 24798 : goto fail;
1271 : }
1272 : #endif
1273 :
1274 499763 : if ((fd == -1) && (errno == ENOTDIR)) {
1275 0 : size_t parsed, len, unparsed;
1276 :
1277 : /*
1278 : * dirfsp does not point at a directory, try a
1279 : * freadlink.
1280 : */
1281 :
1282 33589 : status = read_symlink_reparse(mem_ctx,
1283 : dirfsp,
1284 : NULL,
1285 : &symlink_err);
1286 :
1287 33589 : if (!NT_STATUS_IS_OK(status)) {
1288 16 : DBG_DEBUG("read_symlink_reparse failed: %s\n",
1289 : nt_errstr(status));
1290 16 : status = NT_STATUS_NOT_A_DIRECTORY;
1291 16 : goto fail;
1292 : }
1293 :
1294 33573 : parsed = rel_fname.base_name - path;
1295 33573 : len = talloc_get_size(path);
1296 33573 : unparsed = len - parsed;
1297 :
1298 33573 : if (unparsed > UINT16_MAX) {
1299 0 : status = NT_STATUS_BUFFER_OVERFLOW;
1300 0 : goto fail;
1301 : }
1302 :
1303 33573 : symlink_err->parsed.lnk.unparsed_path_length = unparsed;
1304 :
1305 33573 : status = NT_STATUS_STOPPED_ON_SYMLINK;
1306 33573 : goto fail;
1307 : }
1308 :
1309 466174 : if (fd == -1) {
1310 991 : status = map_nt_error_from_unix(errno);
1311 991 : DBG_DEBUG("SMB_VFS_OPENAT() failed: %s\n",
1312 : strerror(errno));
1313 991 : goto fail;
1314 : }
1315 465183 : fsp_set_fd(fsp, fd);
1316 :
1317 465183 : ok = full_path_extend(&full_fname.base_name, rel_fname.base_name);
1318 465183 : if (!ok) {
1319 0 : goto nomem;
1320 : }
1321 :
1322 465183 : if (next != NULL) {
1323 171079 : struct files_struct *tmp = NULL;
1324 :
1325 171079 : if (dirfsp != in_dirfsp) {
1326 21315 : fd_close(dirfsp);
1327 : }
1328 :
1329 171079 : tmp = dirfsp;
1330 171079 : dirfsp = fsp;
1331 :
1332 171079 : if (tmp == in_dirfsp) {
1333 149764 : status = fsp_new(conn, conn, &fsp);
1334 149764 : if (!NT_STATUS_IS_OK(status)) {
1335 0 : DBG_DEBUG("fsp_new() failed: %s\n",
1336 : nt_errstr(status));
1337 0 : goto fail;
1338 : }
1339 149764 : fsp->fsp_name = &full_fname;
1340 : } else {
1341 21315 : fsp = tmp;
1342 : }
1343 :
1344 171079 : rel_fname.base_name = next;
1345 :
1346 171079 : goto next;
1347 : }
1348 :
1349 294104 : if (dirfsp != in_dirfsp) {
1350 109215 : SMB_ASSERT(fsp_get_pathref_fd(dirfsp) != -1);
1351 109215 : fd_close(dirfsp);
1352 109215 : dirfsp->fsp_name = NULL;
1353 109215 : file_free(NULL, dirfsp);
1354 109215 : dirfsp = NULL;
1355 : }
1356 :
1357 184889 : done:
1358 511564 : fsp->fsp_flags.is_pathref = true;
1359 511564 : fsp->fsp_name = NULL;
1360 :
1361 511564 : status = fsp_set_smb_fname(fsp, &full_fname);
1362 511564 : if (!NT_STATUS_IS_OK(status)) {
1363 0 : DBG_DEBUG("fsp_set_smb_fname() failed: %s\n",
1364 : nt_errstr(status));
1365 0 : goto fail;
1366 : }
1367 :
1368 511564 : status = vfs_stat_fsp(fsp);
1369 511564 : if (!NT_STATUS_IS_OK(status)) {
1370 0 : DBG_DEBUG("vfs_stat_fsp(%s) failed: %s\n",
1371 : fsp_str_dbg(fsp),
1372 : nt_errstr(status));
1373 0 : goto fail;
1374 : }
1375 :
1376 511564 : if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
1377 : /*
1378 : * Last component was a symlink we opened with O_PATH, fail it
1379 : * here.
1380 : */
1381 3723 : status = read_symlink_reparse(mem_ctx,
1382 : fsp,
1383 : NULL,
1384 : &symlink_err);
1385 3723 : if (!NT_STATUS_IS_OK(status)) {
1386 0 : return status;
1387 : }
1388 :
1389 3723 : status = NT_STATUS_STOPPED_ON_SYMLINK;
1390 3723 : goto fail;
1391 : }
1392 :
1393 : /*
1394 : * We must correctly set fsp->file_id as code inside
1395 : * open.c will use this to check if delete_on_close
1396 : * has been set on the dirfsp.
1397 : */
1398 507841 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
1399 :
1400 507841 : result = cp_smb_filename(mem_ctx, fsp->fsp_name);
1401 507841 : if (result == NULL) {
1402 0 : DBG_DEBUG("cp_smb_filename() failed\n");
1403 0 : goto nomem;
1404 : }
1405 :
1406 507841 : status = fsp_smb_fname_link(fsp,
1407 : &result->fsp_link,
1408 : &result->fsp);
1409 507841 : if (!NT_STATUS_IS_OK(status)) {
1410 0 : goto fail;
1411 : }
1412 507841 : talloc_set_destructor(result, smb_fname_fsp_destructor);
1413 :
1414 507841 : *_smb_fname = result;
1415 :
1416 507841 : DBG_DEBUG("returning %s\n", smb_fname_str_dbg(result));
1417 :
1418 507841 : return NT_STATUS_OK;
1419 :
1420 0 : nomem:
1421 0 : status = NT_STATUS_NO_MEMORY;
1422 63122 : fail:
1423 63122 : if (fsp != NULL) {
1424 63122 : if (fsp_get_pathref_fd(fsp) != -1) {
1425 3723 : fd_close(fsp);
1426 : }
1427 63122 : file_free(NULL, fsp);
1428 63122 : fsp = NULL;
1429 : }
1430 :
1431 63122 : if ((dirfsp != NULL) && (dirfsp != in_dirfsp)) {
1432 40549 : SMB_ASSERT(fsp_get_pathref_fd(dirfsp) != -1);
1433 40549 : fd_close(dirfsp);
1434 40549 : dirfsp->fsp_name = NULL;
1435 40549 : file_free(NULL, dirfsp);
1436 40549 : dirfsp = NULL;
1437 : }
1438 :
1439 63122 : if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
1440 62094 : *_symlink_err = symlink_err;
1441 : }
1442 :
1443 63122 : TALLOC_FREE(path);
1444 63122 : return status;
1445 : }
1446 :
1447 : /*
1448 : * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
1449 : * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
1450 : * the first attempt based on the filename sent by the client gives
1451 : * ENOENT.
1452 : */
1453 1557074 : NTSTATUS openat_pathref_fsp_lcomp(struct files_struct *dirfsp,
1454 : struct smb_filename *smb_fname_rel,
1455 : uint32_t ucf_flags)
1456 : {
1457 1557074 : struct connection_struct *conn = dirfsp->conn;
1458 1557074 : const char *orig_rel_base_name = smb_fname_rel->base_name;
1459 1557074 : struct files_struct *fsp = NULL;
1460 1557074 : struct smb_filename *full_fname = NULL;
1461 1557074 : struct vfs_open_how how = {
1462 : .flags = O_RDONLY | O_NONBLOCK | O_NOFOLLOW,
1463 : };
1464 10719 : NTSTATUS status;
1465 10719 : int ret, fd;
1466 :
1467 : /*
1468 : * Make sure we don't need of the all the magic in
1469 : * openat_pathref_fsp() with regards non_widelink_open etc.
1470 : */
1471 :
1472 1557074 : SMB_ASSERT((smb_fname_rel->fsp == NULL) &&
1473 : (dirfsp != dirfsp->conn->cwd_fsp) &&
1474 : (strchr_m(smb_fname_rel->base_name, '/') == NULL) &&
1475 : !is_named_stream(smb_fname_rel));
1476 :
1477 1557074 : SET_STAT_INVALID(smb_fname_rel->st);
1478 :
1479 : /* Check veto files - only looks at last component. */
1480 1557074 : if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
1481 14 : DBG_DEBUG("veto files rejecting last component %s\n",
1482 : smb_fname_str_dbg(smb_fname_rel));
1483 14 : return NT_STATUS_NETWORK_OPEN_RESTRICTION;
1484 : }
1485 :
1486 1557060 : status = fsp_new(conn, conn, &fsp);
1487 1557060 : if (!NT_STATUS_IS_OK(status)) {
1488 0 : DBG_DEBUG("fsp_new() failed: %s\n", nt_errstr(status));
1489 0 : return status;
1490 : }
1491 :
1492 1557060 : GetTimeOfDay(&fsp->open_time);
1493 1557060 : fsp_set_gen_id(fsp);
1494 1557060 : ZERO_STRUCT(conn->sconn->fsp_fi_cache);
1495 :
1496 1557060 : fsp->fsp_flags.is_pathref = true;
1497 :
1498 1557060 : full_fname = full_path_from_dirfsp_atname(conn, dirfsp, smb_fname_rel);
1499 1557060 : if (full_fname == NULL) {
1500 0 : DBG_DEBUG("full_path_from_dirfsp_atname(%s/%s) failed\n",
1501 : dirfsp->fsp_name->base_name,
1502 : smb_fname_rel->base_name);
1503 0 : file_free(NULL, fsp);
1504 0 : return NT_STATUS_NO_MEMORY;
1505 : }
1506 :
1507 1557060 : status = fsp_attach_smb_fname(fsp, &full_fname);
1508 1557060 : if (!NT_STATUS_IS_OK(status)) {
1509 0 : DBG_DEBUG("fsp_attach_smb_fname(fsp, %s) failed: %s\n",
1510 : smb_fname_str_dbg(full_fname),
1511 : nt_errstr(status));
1512 0 : file_free(NULL, fsp);
1513 0 : return status;
1514 : }
1515 :
1516 3103401 : fd = smb_vfs_openat_ci(smb_fname_rel,
1517 2166123 : (ucf_flags & UCF_POSIX_PATHNAMES) ||
1518 619467 : conn->case_sensitive,
1519 : conn,
1520 : dirfsp,
1521 : smb_fname_rel,
1522 : fsp,
1523 : &how);
1524 :
1525 1557060 : if ((fd == -1) && (errno == ENOENT)) {
1526 268611 : status = map_nt_error_from_unix(errno);
1527 268611 : DBG_DEBUG("smb_vfs_openat(%s/%s) failed: %s\n",
1528 : dirfsp->fsp_name->base_name,
1529 : smb_fname_rel->base_name,
1530 : strerror(errno));
1531 268611 : file_free(NULL, fsp);
1532 268611 : return status;
1533 : }
1534 :
1535 1288449 : if (smb_fname_rel->base_name != orig_rel_base_name) {
1536 2148 : struct smb_filename new_fullname = *smb_fname_rel;
1537 :
1538 2148 : DBG_DEBUG("rel->base_name changed from %s to %s\n",
1539 : orig_rel_base_name,
1540 : smb_fname_rel->base_name);
1541 :
1542 2148 : new_fullname.base_name = full_path_from_dirfsp_at_basename(
1543 2148 : talloc_tos(), dirfsp, new_fullname.base_name);
1544 2148 : if (new_fullname.base_name == NULL) {
1545 0 : fd_close(fsp);
1546 0 : file_free(NULL, fsp);
1547 0 : return NT_STATUS_NO_MEMORY;
1548 : }
1549 :
1550 2148 : status = fsp_set_smb_fname(fsp, &new_fullname);
1551 2148 : if (!NT_STATUS_IS_OK(status)) {
1552 0 : fd_close(fsp);
1553 0 : file_free(NULL, fsp);
1554 0 : return status;
1555 : }
1556 : }
1557 :
1558 1288449 : fsp_set_fd(fsp, fd);
1559 :
1560 1288449 : if (fd >= 0) {
1561 1282899 : ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1562 : } else {
1563 5550 : ret = SMB_VFS_FSTATAT(fsp->conn,
1564 : dirfsp,
1565 : smb_fname_rel,
1566 : &fsp->fsp_name->st,
1567 : AT_SYMLINK_NOFOLLOW);
1568 : }
1569 1288449 : if (ret == -1) {
1570 12 : status = map_nt_error_from_unix(errno);
1571 12 : DBG_DEBUG("SMB_VFS_%sSTAT(%s/%s) failed: %s\n",
1572 : (fd >= 0) ? "F" : "",
1573 : dirfsp->fsp_name->base_name,
1574 : smb_fname_rel->base_name,
1575 : strerror(errno));
1576 12 : fd_close(fsp);
1577 12 : file_free(NULL, fsp);
1578 12 : return status;
1579 : }
1580 :
1581 1288437 : fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
1582 1288437 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
1583 :
1584 1288437 : smb_fname_rel->st = fsp->fsp_name->st;
1585 :
1586 1288437 : status = fsp_smb_fname_link(fsp,
1587 : &smb_fname_rel->fsp_link,
1588 : &smb_fname_rel->fsp);
1589 1288437 : if (!NT_STATUS_IS_OK(status)) {
1590 0 : DBG_DEBUG("fsp_smb_fname_link() failed: %s\n",
1591 : nt_errstr(status));
1592 0 : fd_close(fsp);
1593 0 : file_free(NULL, fsp);
1594 0 : return status;
1595 : }
1596 :
1597 1288437 : DBG_DEBUG("fsp [%s]: OK, fd=%d\n", fsp_str_dbg(fsp), fd);
1598 :
1599 1288437 : talloc_set_destructor(smb_fname_rel, smb_fname_fsp_destructor);
1600 1288437 : return NT_STATUS_OK;
1601 : }
1602 :
1603 1865814 : void smb_fname_fsp_unlink(struct smb_filename *smb_fname)
1604 : {
1605 1865814 : talloc_set_destructor(smb_fname, NULL);
1606 1865814 : smb_fname->fsp = NULL;
1607 1865814 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
1608 1865814 : }
1609 :
1610 : /*
1611 : * Move any existing embedded fsp refs from the src name to the
1612 : * destination. It's safe to call this on src smb_fname's that have no embedded
1613 : * pathref fsp.
1614 : */
1615 351287 : NTSTATUS move_smb_fname_fsp_link(struct smb_filename *smb_fname_dst,
1616 : struct smb_filename *smb_fname_src)
1617 : {
1618 9527 : NTSTATUS status;
1619 :
1620 : /*
1621 : * The target should always not be linked yet!
1622 : */
1623 351287 : SMB_ASSERT(smb_fname_dst->fsp == NULL);
1624 351287 : SMB_ASSERT(smb_fname_dst->fsp_link == NULL);
1625 :
1626 351287 : if (smb_fname_src->fsp == NULL) {
1627 0 : return NT_STATUS_OK;
1628 : }
1629 :
1630 351287 : status = fsp_smb_fname_link(smb_fname_src->fsp,
1631 : &smb_fname_dst->fsp_link,
1632 : &smb_fname_dst->fsp);
1633 351287 : if (!NT_STATUS_IS_OK(status)) {
1634 0 : return status;
1635 : }
1636 :
1637 351287 : talloc_set_destructor(smb_fname_dst, smb_fname_fsp_destructor);
1638 :
1639 351287 : smb_fname_fsp_unlink(smb_fname_src);
1640 :
1641 351287 : return NT_STATUS_OK;
1642 : }
1643 :
1644 171660 : static int fsp_ref_no_close_destructor(struct smb_filename *smb_fname)
1645 : {
1646 171660 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
1647 171660 : return 0;
1648 : }
1649 :
1650 175997 : NTSTATUS reference_smb_fname_fsp_link(struct smb_filename *smb_fname_dst,
1651 : const struct smb_filename *smb_fname_src)
1652 : {
1653 377 : NTSTATUS status;
1654 :
1655 : /*
1656 : * The target should always not be linked yet!
1657 : */
1658 175997 : SMB_ASSERT(smb_fname_dst->fsp == NULL);
1659 175997 : SMB_ASSERT(smb_fname_dst->fsp_link == NULL);
1660 :
1661 175997 : if (smb_fname_src->fsp == NULL) {
1662 4337 : return NT_STATUS_OK;
1663 : }
1664 :
1665 171660 : status = fsp_smb_fname_link(smb_fname_src->fsp,
1666 : &smb_fname_dst->fsp_link,
1667 : &smb_fname_dst->fsp);
1668 171660 : if (!NT_STATUS_IS_OK(status)) {
1669 0 : return status;
1670 : }
1671 :
1672 171660 : talloc_set_destructor(smb_fname_dst, fsp_ref_no_close_destructor);
1673 :
1674 171660 : return NT_STATUS_OK;
1675 : }
1676 :
1677 : /**
1678 : * Create an smb_fname and open smb_fname->fsp pathref
1679 : **/
1680 343591 : NTSTATUS synthetic_pathref(TALLOC_CTX *mem_ctx,
1681 : struct files_struct *dirfsp,
1682 : const char *base_name,
1683 : const char *stream_name,
1684 : const SMB_STRUCT_STAT *psbuf,
1685 : NTTIME twrp,
1686 : uint32_t flags,
1687 : struct smb_filename **_smb_fname)
1688 : {
1689 343591 : struct smb_filename *smb_fname = NULL;
1690 1958 : NTSTATUS status;
1691 :
1692 343591 : smb_fname = synthetic_smb_fname(mem_ctx,
1693 : base_name,
1694 : stream_name,
1695 : psbuf,
1696 : twrp,
1697 : flags);
1698 343591 : if (smb_fname == NULL) {
1699 0 : return NT_STATUS_NO_MEMORY;
1700 : }
1701 :
1702 343591 : status = openat_pathref_fsp(dirfsp, smb_fname);
1703 343591 : if (!NT_STATUS_IS_OK(status)) {
1704 207257 : DBG_NOTICE("opening [%s] failed\n",
1705 : smb_fname_str_dbg(smb_fname));
1706 207257 : TALLOC_FREE(smb_fname);
1707 207257 : return status;
1708 : }
1709 :
1710 136334 : *_smb_fname = smb_fname;
1711 136334 : return NT_STATUS_OK;
1712 : }
1713 :
1714 : /**
1715 : * Turn a path into a parent pathref and atname
1716 : *
1717 : * This returns the parent pathref in _parent and the name relative to it. If
1718 : * smb_fname was a pathref (ie smb_fname->fsp != NULL), then _atname will be a
1719 : * pathref as well, ie _atname->fsp will point at the same fsp as
1720 : * smb_fname->fsp.
1721 : **/
1722 175065 : NTSTATUS parent_pathref(TALLOC_CTX *mem_ctx,
1723 : struct files_struct *dirfsp,
1724 : const struct smb_filename *smb_fname,
1725 : struct smb_filename **_parent,
1726 : struct smb_filename **_atname)
1727 : {
1728 175065 : struct smb_filename *parent = NULL;
1729 175065 : struct smb_filename *atname = NULL;
1730 361 : NTSTATUS status;
1731 :
1732 175065 : status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
1733 : mem_ctx,
1734 : smb_fname,
1735 : &parent,
1736 : &atname);
1737 175065 : if (!NT_STATUS_IS_OK(status)) {
1738 0 : return status;
1739 : }
1740 :
1741 : /*
1742 : * We know that the parent name must
1743 : * exist, and the name has been canonicalized
1744 : * even if this was a POSIX pathname.
1745 : * Ensure that we follow symlinks for
1746 : * the parent. See the torture test
1747 : * POSIX-SYMLINK-PARENT for details.
1748 : */
1749 175065 : parent->flags &= ~SMB_FILENAME_POSIX_PATH;
1750 :
1751 175065 : status = openat_pathref_fsp(dirfsp, parent);
1752 175065 : if (!NT_STATUS_IS_OK(status)) {
1753 0 : TALLOC_FREE(parent);
1754 0 : return status;
1755 : }
1756 :
1757 175065 : status = reference_smb_fname_fsp_link(atname, smb_fname);
1758 175065 : if (!NT_STATUS_IS_OK(status)) {
1759 0 : TALLOC_FREE(parent);
1760 0 : return status;
1761 : }
1762 :
1763 175065 : *_parent = parent;
1764 175065 : *_atname = atname;
1765 175065 : return NT_STATUS_OK;
1766 : }
1767 :
1768 3106 : static bool close_file_in_loop(struct files_struct *fsp,
1769 : enum file_close_type close_type)
1770 : {
1771 3106 : if (fsp_is_alternate_stream(fsp)) {
1772 : /*
1773 : * This is a stream, it can't be a base
1774 : */
1775 72 : SMB_ASSERT(fsp->stream_fsp == NULL);
1776 72 : SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1777 :
1778 : /*
1779 : * Remove the base<->stream link so that
1780 : * close_file_free() does not close fsp->base_fsp as
1781 : * well. This would destroy walking the linked list of
1782 : * fsps.
1783 : */
1784 72 : fsp->base_fsp->stream_fsp = NULL;
1785 72 : fsp->base_fsp = NULL;
1786 :
1787 72 : close_file_free(NULL, &fsp, close_type);
1788 72 : return NULL;
1789 : }
1790 :
1791 3034 : if (fsp->stream_fsp != NULL) {
1792 : /*
1793 : * This is the base of a stream.
1794 : */
1795 0 : SMB_ASSERT(fsp->stream_fsp->base_fsp == fsp);
1796 :
1797 : /*
1798 : * Remove the base<->stream link. This will make fsp
1799 : * look like a normal fsp for the next round.
1800 : */
1801 0 : fsp->stream_fsp->base_fsp = NULL;
1802 0 : fsp->stream_fsp = NULL;
1803 :
1804 : /*
1805 : * Have us called back a second time. In the second
1806 : * round, "fsp" now looks like a normal fsp.
1807 : */
1808 0 : return false;
1809 : }
1810 :
1811 3034 : close_file_free(NULL, &fsp, close_type);
1812 3034 : return true;
1813 : }
1814 :
1815 : /****************************************************************************
1816 : Close all open files for a connection.
1817 : ****************************************************************************/
1818 :
1819 : struct file_close_conn_state {
1820 : struct connection_struct *conn;
1821 : enum file_close_type close_type;
1822 : bool fsp_left_behind;
1823 : };
1824 :
1825 1714 : static struct files_struct *file_close_conn_fn(
1826 : struct files_struct *fsp,
1827 : void *private_data)
1828 : {
1829 1714 : struct file_close_conn_state *state = private_data;
1830 8 : bool did_close;
1831 :
1832 1714 : if (fsp->conn != state->conn) {
1833 1274 : return NULL;
1834 : }
1835 :
1836 438 : if (fsp->op != NULL && fsp->op->global->durable) {
1837 : /*
1838 : * A tree disconnect closes a durable handle
1839 : */
1840 4 : fsp->op->global->durable = false;
1841 : }
1842 :
1843 438 : did_close = close_file_in_loop(fsp, state->close_type);
1844 438 : if (!did_close) {
1845 0 : state->fsp_left_behind = true;
1846 : }
1847 :
1848 432 : return NULL;
1849 : }
1850 :
1851 48683 : void file_close_conn(connection_struct *conn, enum file_close_type close_type)
1852 : {
1853 48683 : struct file_close_conn_state state = { .conn = conn,
1854 : .close_type = close_type };
1855 :
1856 48683 : files_forall(conn->sconn, file_close_conn_fn, &state);
1857 :
1858 48683 : if (state.fsp_left_behind) {
1859 0 : state.fsp_left_behind = false;
1860 0 : files_forall(conn->sconn, file_close_conn_fn, &state);
1861 0 : SMB_ASSERT(!state.fsp_left_behind);
1862 : }
1863 48683 : }
1864 :
1865 : /****************************************************************************
1866 : Initialise file structures.
1867 : ****************************************************************************/
1868 :
1869 : static int files_max_open_fds;
1870 :
1871 31581 : bool file_init_global(void)
1872 : {
1873 31581 : int request_max = lp_max_open_files();
1874 842 : int real_lim;
1875 842 : int real_max;
1876 :
1877 31581 : if (files_max_open_fds != 0) {
1878 30721 : return true;
1879 : }
1880 :
1881 : /*
1882 : * Set the max_open files to be the requested
1883 : * max plus a fudgefactor to allow for the extra
1884 : * fd's we need such as log files etc...
1885 : */
1886 18 : real_lim = set_maxfiles(request_max + MAX_OPEN_FUDGEFACTOR);
1887 :
1888 18 : real_max = real_lim - MAX_OPEN_FUDGEFACTOR;
1889 :
1890 18 : if (real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) {
1891 0 : real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
1892 : }
1893 :
1894 18 : if (real_max != request_max) {
1895 0 : DEBUG(1, ("file_init_global: Information only: requested %d "
1896 : "open files, %d are available.\n",
1897 : request_max, real_max));
1898 : }
1899 :
1900 18 : SMB_ASSERT(real_max > 100);
1901 :
1902 18 : files_max_open_fds = real_max;
1903 18 : return true;
1904 : }
1905 :
1906 31581 : bool file_init(struct smbd_server_connection *sconn)
1907 : {
1908 842 : bool ok;
1909 :
1910 31581 : ok = file_init_global();
1911 31581 : if (!ok) {
1912 0 : return false;
1913 : }
1914 :
1915 31581 : sconn->real_max_open_files = files_max_open_fds;
1916 :
1917 31581 : return true;
1918 : }
1919 :
1920 : /****************************************************************************
1921 : Close files open by a specified vuid.
1922 : ****************************************************************************/
1923 :
1924 : struct file_close_user_state {
1925 : uint64_t vuid;
1926 : bool fsp_left_behind;
1927 : };
1928 :
1929 2892 : static struct files_struct *file_close_user_fn(
1930 : struct files_struct *fsp,
1931 : void *private_data)
1932 : {
1933 2892 : struct file_close_user_state *state = private_data;
1934 290 : bool did_close;
1935 :
1936 2892 : if (fsp->vuid != state->vuid) {
1937 222 : return NULL;
1938 : }
1939 :
1940 2668 : did_close = close_file_in_loop(fsp, SHUTDOWN_CLOSE);
1941 2668 : if (!did_close) {
1942 72 : state->fsp_left_behind = true;
1943 : }
1944 :
1945 2380 : return NULL;
1946 : }
1947 :
1948 32243 : void file_close_user(struct smbd_server_connection *sconn, uint64_t vuid)
1949 : {
1950 32243 : struct file_close_user_state state = { .vuid = vuid };
1951 :
1952 32243 : files_forall(sconn, file_close_user_fn, &state);
1953 :
1954 32243 : if (state.fsp_left_behind) {
1955 36 : state.fsp_left_behind = false;
1956 36 : files_forall(sconn, file_close_user_fn, &state);
1957 36 : SMB_ASSERT(!state.fsp_left_behind);
1958 : }
1959 32243 : }
1960 :
1961 : /*
1962 : * Walk the files table until "fn" returns non-NULL
1963 : */
1964 :
1965 233602 : struct files_struct *files_forall(
1966 : struct smbd_server_connection *sconn,
1967 : struct files_struct *(*fn)(struct files_struct *fsp,
1968 : void *private_data),
1969 : void *private_data)
1970 : {
1971 1889 : struct files_struct *fsp, *next;
1972 :
1973 458835 : for (fsp = sconn->files; fsp; fsp = next) {
1974 373 : struct files_struct *ret;
1975 227214 : next = fsp->next;
1976 227214 : ret = fn(fsp, private_data);
1977 227214 : if (ret != NULL) {
1978 1981 : return ret;
1979 : }
1980 : }
1981 229746 : return NULL;
1982 : }
1983 :
1984 : /****************************************************************************
1985 : Find a fsp given a file descriptor.
1986 : ****************************************************************************/
1987 :
1988 4 : files_struct *file_find_fd(struct smbd_server_connection *sconn, int fd)
1989 : {
1990 4 : int count=0;
1991 0 : files_struct *fsp;
1992 :
1993 5 : for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
1994 5 : if (fsp_get_pathref_fd(fsp) == fd) {
1995 4 : if (count > 10) {
1996 0 : DLIST_PROMOTE(sconn->files, fsp);
1997 : }
1998 4 : return fsp;
1999 : }
2000 : }
2001 :
2002 0 : return NULL;
2003 : }
2004 :
2005 : /****************************************************************************
2006 : Find a fsp given a device, inode and file_id.
2007 : ****************************************************************************/
2008 :
2009 14638 : files_struct *file_find_dif(struct smbd_server_connection *sconn,
2010 : struct file_id id, unsigned long gen_id)
2011 : {
2012 14638 : int count=0;
2013 71 : files_struct *fsp;
2014 :
2015 14638 : if (gen_id == 0) {
2016 0 : return NULL;
2017 : }
2018 :
2019 202921 : for (fsp = sconn->files; fsp; fsp = fsp->next,count++) {
2020 : /*
2021 : * We can have a fsp->fh->fd == -1 here as it could be a stat
2022 : * open.
2023 : */
2024 202921 : if (!file_id_equal(&fsp->file_id, &id)) {
2025 17109 : continue;
2026 : }
2027 185812 : if (!fsp->fsp_flags.is_fsa) {
2028 14655 : continue;
2029 : }
2030 171157 : if (fh_get_gen_id(fsp->fh) != gen_id) {
2031 156519 : continue;
2032 : }
2033 14638 : if (count > 10) {
2034 4646 : DLIST_PROMOTE(sconn->files, fsp);
2035 : }
2036 14567 : return fsp;
2037 : }
2038 :
2039 0 : return NULL;
2040 : }
2041 :
2042 : /****************************************************************************
2043 : Find the first fsp given a device and inode.
2044 : We use a singleton cache here to speed up searching from getfilepathinfo
2045 : calls.
2046 : ****************************************************************************/
2047 :
2048 12409 : files_struct *file_find_di_first(struct smbd_server_connection *sconn,
2049 : struct file_id id,
2050 : bool need_fsa)
2051 : {
2052 301 : files_struct *fsp;
2053 :
2054 12409 : if (file_id_equal(&sconn->fsp_fi_cache.id, &id)) {
2055 : /* Positive or negative cache hit. */
2056 0 : return sconn->fsp_fi_cache.fsp;
2057 : }
2058 :
2059 12409 : sconn->fsp_fi_cache.id = id;
2060 :
2061 40269 : for (fsp=sconn->files;fsp;fsp=fsp->next) {
2062 31623 : if (need_fsa && !fsp->fsp_flags.is_fsa) {
2063 21228 : continue;
2064 : }
2065 10395 : if (file_id_equal(&fsp->file_id, &id)) {
2066 : /* Setup positive cache. */
2067 3763 : sconn->fsp_fi_cache.fsp = fsp;
2068 3763 : return fsp;
2069 : }
2070 : }
2071 :
2072 : /* Setup negative cache. */
2073 8646 : sconn->fsp_fi_cache.fsp = NULL;
2074 8646 : return NULL;
2075 : }
2076 :
2077 : /****************************************************************************
2078 : Find the next fsp having the same device and inode.
2079 : ****************************************************************************/
2080 :
2081 2069 : files_struct *file_find_di_next(files_struct *start_fsp,
2082 : bool need_fsa)
2083 : {
2084 21 : files_struct *fsp;
2085 :
2086 2891 : for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
2087 977 : if (need_fsa && !fsp->fsp_flags.is_fsa) {
2088 0 : continue;
2089 : }
2090 977 : if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
2091 155 : return fsp;
2092 : }
2093 : }
2094 :
2095 1898 : return NULL;
2096 : }
2097 :
2098 4 : struct files_struct *file_find_one_fsp_from_lease_key(
2099 : struct smbd_server_connection *sconn,
2100 : const struct smb2_lease_key *lease_key)
2101 : {
2102 0 : struct files_struct *fsp;
2103 :
2104 6 : for (fsp = sconn->files; fsp; fsp=fsp->next) {
2105 6 : if ((fsp->lease != NULL) &&
2106 4 : (fsp->lease->lease.lease_key.data[0] ==
2107 4 : lease_key->data[0]) &&
2108 4 : (fsp->lease->lease.lease_key.data[1] ==
2109 4 : lease_key->data[1])) {
2110 4 : return fsp;
2111 : }
2112 : }
2113 0 : return NULL;
2114 : }
2115 :
2116 : /****************************************************************************
2117 : Find any fsp open with a pathname below that of an already open path.
2118 : ****************************************************************************/
2119 :
2120 19 : bool file_find_subpath(files_struct *dir_fsp)
2121 : {
2122 5 : files_struct *fsp;
2123 5 : size_t dlen;
2124 19 : char *d_fullname = NULL;
2125 :
2126 19 : d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
2127 19 : dir_fsp->conn->connectpath,
2128 19 : dir_fsp->fsp_name->base_name);
2129 :
2130 19 : if (!d_fullname) {
2131 0 : return false;
2132 : }
2133 :
2134 19 : dlen = strlen(d_fullname);
2135 :
2136 86 : for (fsp=dir_fsp->conn->sconn->files; fsp; fsp=fsp->next) {
2137 20 : char *d1_fullname;
2138 :
2139 70 : if (fsp == dir_fsp) {
2140 19 : continue;
2141 : }
2142 :
2143 51 : d1_fullname = talloc_asprintf(talloc_tos(),
2144 : "%s/%s",
2145 51 : fsp->conn->connectpath,
2146 51 : fsp->fsp_name->base_name);
2147 :
2148 : /*
2149 : * If the open file has a path that is a longer
2150 : * component, then it's a subpath.
2151 : */
2152 51 : if (strnequal(d_fullname, d1_fullname, dlen) &&
2153 15 : (d1_fullname[dlen] == '/')) {
2154 3 : TALLOC_FREE(d1_fullname);
2155 3 : TALLOC_FREE(d_fullname);
2156 3 : return true;
2157 : }
2158 53 : TALLOC_FREE(d1_fullname);
2159 : }
2160 :
2161 16 : TALLOC_FREE(d_fullname);
2162 16 : return false;
2163 : }
2164 :
2165 : /****************************************************************************
2166 : Free up a fsp.
2167 : ****************************************************************************/
2168 :
2169 6284180 : static void fsp_free(files_struct *fsp)
2170 : {
2171 6284180 : struct smbd_server_connection *sconn = fsp->conn->sconn;
2172 :
2173 6284180 : if (fsp == sconn->fsp_fi_cache.fsp) {
2174 517 : ZERO_STRUCT(sconn->fsp_fi_cache);
2175 : }
2176 :
2177 6284180 : DLIST_REMOVE(sconn->files, fsp);
2178 6284180 : SMB_ASSERT(sconn->num_files > 0);
2179 6284180 : sconn->num_files--;
2180 :
2181 6284180 : TALLOC_FREE(fsp->fake_file_handle);
2182 :
2183 6284180 : if (fh_get_refcount(fsp->fh) == 1) {
2184 6284067 : TALLOC_FREE(fsp->fh);
2185 : } else {
2186 113 : size_t new_refcount = fh_get_refcount(fsp->fh) - 1;
2187 113 : fh_set_refcount(fsp->fh, new_refcount);
2188 : }
2189 :
2190 6284180 : if (fsp->lease != NULL) {
2191 1024 : if (fsp->lease->ref_count == 1) {
2192 812 : TALLOC_FREE(fsp->lease);
2193 : } else {
2194 212 : fsp->lease->ref_count--;
2195 : }
2196 : }
2197 :
2198 6284180 : fsp->conn->num_files_open--;
2199 :
2200 6284180 : if (fsp->fsp_name != NULL &&
2201 6134406 : fsp->fsp_name->fsp_link != NULL)
2202 : {
2203 : /*
2204 : * Free fsp_link of fsp->fsp_name. To do this in the correct
2205 : * talloc destructor order we have to do it here. The
2206 : * talloc_free() of the link should set the fsp pointer to NULL.
2207 : */
2208 6074979 : TALLOC_FREE(fsp->fsp_name->fsp_link);
2209 6074979 : SMB_ASSERT(fsp->fsp_name->fsp == NULL);
2210 : }
2211 :
2212 : /* this is paranoia, just in case someone tries to reuse the
2213 : information */
2214 6284180 : ZERO_STRUCTP(fsp);
2215 :
2216 : /* fsp->fsp_name is a talloc child and is free'd automatically. */
2217 6284180 : TALLOC_FREE(fsp);
2218 6284180 : }
2219 :
2220 : /*
2221 : * Rundown of all smb-related sub-structures of an fsp
2222 : */
2223 6869320 : void fsp_unbind_smb(struct smb_request *req, files_struct *fsp)
2224 : {
2225 6869320 : if (fsp == fsp->conn->cwd_fsp) {
2226 0 : return;
2227 : }
2228 :
2229 6869320 : if (fsp->notify) {
2230 1866 : size_t len = fsp_fullbasepath(fsp, NULL, 0);
2231 1866 : char fullpath[len+1];
2232 :
2233 1866 : fsp_fullbasepath(fsp, fullpath, sizeof(fullpath));
2234 :
2235 1866 : notify_remove(fsp->conn->sconn->notify_ctx, fsp, fullpath);
2236 1866 : TALLOC_FREE(fsp->notify);
2237 : }
2238 :
2239 : /* Ensure this event will never fire. */
2240 6869320 : TALLOC_FREE(fsp->update_write_time_event);
2241 :
2242 6869320 : if (fsp->op != NULL) {
2243 568091 : fsp->op->compat = NULL;
2244 : }
2245 6869320 : TALLOC_FREE(fsp->op);
2246 :
2247 6869320 : if ((req != NULL) && (fsp == req->chain_fsp)) {
2248 556306 : req->chain_fsp = NULL;
2249 : }
2250 :
2251 : /*
2252 : * Clear all possible chained fsp
2253 : * pointers in the SMB2 request queue.
2254 : */
2255 6869320 : remove_smb2_chained_fsp(fsp);
2256 : }
2257 :
2258 6284180 : void file_free(struct smb_request *req, files_struct *fsp)
2259 : {
2260 6284180 : struct smbd_server_connection *sconn = fsp->conn->sconn;
2261 6284180 : uint64_t fnum = fsp->fnum;
2262 :
2263 6284180 : fsp_unbind_smb(req, fsp);
2264 :
2265 : /* Drop all remaining extensions. */
2266 6284180 : vfs_remove_all_fsp_extensions(fsp);
2267 :
2268 6284180 : fsp_free(fsp);
2269 :
2270 6284180 : DBG_INFO("freed files structure %"PRIu64" (%zu used)\n",
2271 : fnum,
2272 : sconn->num_files);
2273 6284180 : }
2274 :
2275 : /****************************************************************************
2276 : Get an fsp from a packet given a 16 bit fnum.
2277 : ****************************************************************************/
2278 :
2279 212009 : files_struct *file_fsp(struct smb_request *req, uint16_t fid)
2280 : {
2281 1269 : struct smbXsrv_open *op;
2282 1269 : NTSTATUS status;
2283 212009 : NTTIME now = 0;
2284 1269 : files_struct *fsp;
2285 :
2286 212009 : if (req == NULL) {
2287 : /*
2288 : * We should never get here. req==NULL could in theory
2289 : * only happen from internal opens with a non-zero
2290 : * root_dir_fid. Internal opens just don't do that, at
2291 : * least they are not supposed to do so. And if they
2292 : * start to do so, they better fake up a smb_request
2293 : * from which we get the right smbd_server_conn. While
2294 : * this should never happen, let's return NULL here.
2295 : */
2296 0 : return NULL;
2297 : }
2298 :
2299 212009 : if (req->chain_fsp != NULL) {
2300 102 : if (req->chain_fsp->fsp_flags.closing) {
2301 0 : return NULL;
2302 : }
2303 102 : return req->chain_fsp;
2304 : }
2305 :
2306 211907 : if (req->xconn == NULL) {
2307 0 : return NULL;
2308 : }
2309 :
2310 211907 : now = timeval_to_nttime(&req->request_time);
2311 :
2312 211907 : status = smb1srv_open_lookup(req->xconn,
2313 : fid, now, &op);
2314 211907 : if (!NT_STATUS_IS_OK(status)) {
2315 2688 : return NULL;
2316 : }
2317 :
2318 209160 : fsp = op->compat;
2319 209160 : if (fsp == NULL) {
2320 0 : return NULL;
2321 : }
2322 :
2323 209160 : if (fsp->fsp_flags.closing) {
2324 0 : return NULL;
2325 : }
2326 :
2327 209160 : req->chain_fsp = fsp;
2328 209160 : fsp->fsp_name->st.cached_dos_attributes = FILE_ATTRIBUTE_INVALID;
2329 209160 : return fsp;
2330 : }
2331 :
2332 841147 : struct files_struct *file_fsp_get(struct smbd_smb2_request *smb2req,
2333 : uint64_t persistent_id,
2334 : uint64_t volatile_id)
2335 : {
2336 7957 : struct smbXsrv_open *op;
2337 7957 : NTSTATUS status;
2338 841147 : NTTIME now = 0;
2339 7957 : struct files_struct *fsp;
2340 :
2341 841147 : now = timeval_to_nttime(&smb2req->request_time);
2342 :
2343 841147 : status = smb2srv_open_lookup(smb2req->xconn,
2344 : persistent_id, volatile_id,
2345 : now, &op);
2346 841147 : if (!NT_STATUS_IS_OK(status)) {
2347 14019 : return NULL;
2348 : }
2349 :
2350 827128 : fsp = op->compat;
2351 827128 : if (fsp == NULL) {
2352 0 : return NULL;
2353 : }
2354 :
2355 827128 : if (smb2req->tcon == NULL) {
2356 0 : return NULL;
2357 : }
2358 :
2359 827128 : if (smb2req->tcon->compat != fsp->conn) {
2360 4 : return NULL;
2361 : }
2362 :
2363 827124 : if (smb2req->session == NULL) {
2364 0 : return NULL;
2365 : }
2366 :
2367 827124 : if (smb2req->session->global->session_wire_id != fsp->vuid) {
2368 0 : return NULL;
2369 : }
2370 :
2371 827124 : if (fsp->fsp_flags.closing) {
2372 0 : return NULL;
2373 : }
2374 :
2375 827124 : fsp->fsp_name->st.cached_dos_attributes = FILE_ATTRIBUTE_INVALID;
2376 :
2377 827124 : return fsp;
2378 : }
2379 :
2380 1668169 : struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
2381 : uint64_t persistent_id,
2382 : uint64_t volatile_id)
2383 : {
2384 15912 : struct files_struct *fsp;
2385 :
2386 1668169 : if (smb2req->compat_chain_fsp != NULL) {
2387 827022 : if (smb2req->compat_chain_fsp->fsp_flags.closing) {
2388 0 : return NULL;
2389 : }
2390 827022 : smb2req->compat_chain_fsp->fsp_name->st.cached_dos_attributes =
2391 : FILE_ATTRIBUTE_INVALID;
2392 827022 : return smb2req->compat_chain_fsp;
2393 : }
2394 :
2395 841147 : fsp = file_fsp_get(smb2req, persistent_id, volatile_id);
2396 841147 : if (fsp == NULL) {
2397 14023 : return NULL;
2398 : }
2399 :
2400 827124 : smb2req->compat_chain_fsp = fsp;
2401 827124 : return fsp;
2402 : }
2403 :
2404 : /****************************************************************************
2405 : Duplicate the file handle part for a DOS or FCB open.
2406 : ****************************************************************************/
2407 :
2408 113 : NTSTATUS dup_file_fsp(
2409 : files_struct *from,
2410 : uint32_t access_mask,
2411 : files_struct *to)
2412 : {
2413 1 : size_t new_refcount;
2414 :
2415 : /* this can never happen for print files */
2416 113 : SMB_ASSERT(from->print_file == NULL);
2417 :
2418 113 : TALLOC_FREE(to->fh);
2419 :
2420 113 : to->fh = from->fh;
2421 113 : new_refcount = fh_get_refcount(to->fh) + 1;
2422 113 : fh_set_refcount(to->fh, new_refcount);
2423 :
2424 113 : to->file_id = from->file_id;
2425 113 : to->initial_allocation_size = from->initial_allocation_size;
2426 113 : to->file_pid = from->file_pid;
2427 113 : to->vuid = from->vuid;
2428 113 : to->open_time = from->open_time;
2429 113 : to->access_mask = access_mask;
2430 113 : to->oplock_type = from->oplock_type;
2431 113 : to->fsp_flags.can_lock = from->fsp_flags.can_lock;
2432 113 : to->fsp_flags.can_read = ((access_mask & FILE_READ_DATA) != 0);
2433 114 : to->fsp_flags.can_write =
2434 225 : CAN_WRITE(from->conn) &&
2435 113 : ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
2436 113 : if (from->fsp_name->twrp != 0) {
2437 0 : to->fsp_flags.can_write = false;
2438 : }
2439 113 : to->fsp_flags.modified = from->fsp_flags.modified;
2440 113 : to->fsp_flags.is_directory = from->fsp_flags.is_directory;
2441 113 : to->fsp_flags.aio_write_behind = from->fsp_flags.aio_write_behind;
2442 113 : to->fsp_flags.is_fsa = from->fsp_flags.is_fsa;
2443 113 : to->fsp_flags.is_pathref = from->fsp_flags.is_pathref;
2444 113 : to->fsp_flags.have_proc_fds = from->fsp_flags.have_proc_fds;
2445 113 : to->fsp_flags.is_dirfsp = from->fsp_flags.is_dirfsp;
2446 :
2447 113 : return fsp_set_smb_fname(to, from->fsp_name);
2448 : }
2449 :
2450 : /**
2451 : * Return a jenkins hash of a pathname on a connection.
2452 : */
2453 :
2454 6216579 : NTSTATUS file_name_hash(connection_struct *conn,
2455 : const char *name, uint32_t *p_name_hash)
2456 : {
2457 32963 : char tmpbuf[PATH_MAX];
2458 32963 : char *fullpath, *to_free;
2459 32963 : ssize_t len;
2460 32963 : TDB_DATA key;
2461 :
2462 : /* Set the hash of the full pathname. */
2463 :
2464 6216579 : if (name[0] == '/') {
2465 1446281 : strlcpy(tmpbuf, name, sizeof(tmpbuf));
2466 1446281 : fullpath = tmpbuf;
2467 1446281 : len = strlen(fullpath);
2468 1446281 : to_free = NULL;
2469 : } else {
2470 4770298 : len = full_path_tos(conn->connectpath,
2471 : name,
2472 : tmpbuf,
2473 : sizeof(tmpbuf),
2474 : &fullpath,
2475 : &to_free);
2476 : }
2477 6216579 : if (len == -1) {
2478 0 : return NT_STATUS_NO_MEMORY;
2479 : }
2480 6216579 : key = (TDB_DATA) { .dptr = (uint8_t *)fullpath, .dsize = len+1 };
2481 6216579 : *p_name_hash = tdb_jenkins_hash(&key);
2482 :
2483 6216579 : DEBUG(10,("file_name_hash: %s hash 0x%x\n",
2484 : fullpath,
2485 : (unsigned int)*p_name_hash ));
2486 :
2487 6216579 : TALLOC_FREE(to_free);
2488 6216579 : return NT_STATUS_OK;
2489 : }
2490 :
2491 6080547 : static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
2492 : struct smb_filename **_smb_fname)
2493 : {
2494 6080547 : TALLOC_CTX *frame = talloc_stackframe();
2495 6080547 : struct smb_filename *smb_fname_new = talloc_move(fsp, _smb_fname);
2496 6080547 : const char *name_str = NULL;
2497 6080547 : uint32_t name_hash = 0;
2498 32313 : NTSTATUS status;
2499 :
2500 6080547 : name_str = smb_fname_str_dbg(smb_fname_new);
2501 6080547 : if (name_str == NULL) {
2502 0 : TALLOC_FREE(frame);
2503 0 : return NT_STATUS_NO_MEMORY;
2504 : }
2505 :
2506 6080547 : status = file_name_hash(fsp->conn,
2507 : name_str,
2508 : &name_hash);
2509 6080547 : TALLOC_FREE(frame);
2510 6080547 : name_str = NULL;
2511 6080547 : if (!NT_STATUS_IS_OK(status)) {
2512 0 : return status;
2513 : }
2514 :
2515 6080547 : status = fsp_smb_fname_link(fsp,
2516 : &smb_fname_new->fsp_link,
2517 : &smb_fname_new->fsp);
2518 6080547 : if (!NT_STATUS_IS_OK(status)) {
2519 0 : return status;
2520 : }
2521 :
2522 6080547 : fsp->name_hash = name_hash;
2523 6080547 : fsp->fsp_name = smb_fname_new;
2524 6080547 : fsp->fsp_name->st.cached_dos_attributes = FILE_ATTRIBUTE_INVALID;
2525 6080547 : *_smb_fname = NULL;
2526 6080547 : return NT_STATUS_OK;
2527 : }
2528 :
2529 : /**
2530 : * The only way that the fsp->fsp_name field should ever be set.
2531 : */
2532 1100910 : NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
2533 : const struct smb_filename *smb_fname_in)
2534 : {
2535 1100910 : struct smb_filename *smb_fname_old = fsp->fsp_name;
2536 1100910 : struct smb_filename *smb_fname_new = NULL;
2537 11069 : NTSTATUS status;
2538 :
2539 1100910 : smb_fname_new = cp_smb_filename(fsp, smb_fname_in);
2540 1100910 : if (smb_fname_new == NULL) {
2541 0 : return NT_STATUS_NO_MEMORY;
2542 : }
2543 :
2544 1100910 : status = fsp_attach_smb_fname(fsp, &smb_fname_new);
2545 1100910 : if (!NT_STATUS_IS_OK(status)) {
2546 0 : TALLOC_FREE(smb_fname_new);
2547 0 : return status;
2548 : }
2549 :
2550 1100910 : if (smb_fname_old != NULL) {
2551 589216 : smb_fname_fsp_unlink(smb_fname_old);
2552 589216 : TALLOC_FREE(smb_fname_old);
2553 : }
2554 :
2555 1100910 : return NT_STATUS_OK;
2556 : }
2557 :
2558 7466 : size_t fsp_fullbasepath(struct files_struct *fsp, char *buf, size_t buflen)
2559 : {
2560 7466 : int len = 0;
2561 :
2562 7466 : if (buf == NULL) {
2563 : /*
2564 : * susv4 allows buf==NULL if buflen==0 for snprintf.
2565 : */
2566 3734 : SMB_ASSERT(buflen == 0);
2567 : }
2568 :
2569 7466 : if (ISDOT(fsp->fsp_name->base_name)) {
2570 384 : len = snprintf(buf, buflen, "%s", fsp->conn->connectpath);
2571 : } else {
2572 7082 : len = snprintf(buf,
2573 : buflen,
2574 : "%s/%s",
2575 7082 : fsp->conn->connectpath,
2576 7082 : fsp->fsp_name->base_name);
2577 : }
2578 7466 : SMB_ASSERT(len > 0);
2579 :
2580 7466 : return len;
2581 : }
2582 :
2583 4950134 : void fsp_set_base_fsp(struct files_struct *fsp, struct files_struct *base_fsp)
2584 : {
2585 4950134 : SMB_ASSERT(fsp->stream_fsp == NULL);
2586 4950134 : if (base_fsp != NULL) {
2587 15505 : SMB_ASSERT(base_fsp->base_fsp == NULL);
2588 15505 : SMB_ASSERT(base_fsp->stream_fsp == NULL);
2589 : }
2590 :
2591 4950134 : if (fsp->base_fsp != NULL) {
2592 7430 : SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
2593 7430 : fsp->base_fsp->stream_fsp = NULL;
2594 : }
2595 :
2596 4950134 : fsp->base_fsp = base_fsp;
2597 4950134 : if (fsp->base_fsp != NULL) {
2598 15505 : fsp->base_fsp->stream_fsp = fsp;
2599 : }
2600 4950134 : }
2601 :
2602 21904850 : bool fsp_is_alternate_stream(const struct files_struct *fsp)
2603 : {
2604 21904850 : return (fsp->base_fsp != NULL);
2605 : }
2606 :
2607 4605437 : struct files_struct *metadata_fsp(struct files_struct *fsp)
2608 : {
2609 4605437 : if (fsp_is_alternate_stream(fsp)) {
2610 22005 : return fsp->base_fsp;
2611 : }
2612 4573975 : return fsp;
2613 : }
2614 :
2615 414092 : static bool fsp_generic_ask_sharemode(struct files_struct *fsp)
2616 : {
2617 414092 : if (fsp == NULL) {
2618 0 : return false;
2619 : }
2620 :
2621 414092 : if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
2622 : /* Always use filesystem for UNIX mtime query. */
2623 1530 : return false;
2624 : }
2625 :
2626 410990 : return true;
2627 : }
2628 :
2629 29958 : bool fsp_search_ask_sharemode(struct files_struct *fsp)
2630 : {
2631 29958 : if (!fsp_generic_ask_sharemode(fsp)) {
2632 24 : return false;
2633 : }
2634 :
2635 29934 : return lp_smbd_search_ask_sharemode(SNUM(fsp->conn));
2636 : }
2637 :
2638 384134 : bool fsp_getinfo_ask_sharemode(struct files_struct *fsp)
2639 : {
2640 384134 : if (!fsp_generic_ask_sharemode(fsp)) {
2641 1506 : return false;
2642 : }
2643 :
2644 382628 : return lp_smbd_getinfo_ask_sharemode(SNUM(fsp->conn));
2645 : }
|