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