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 :
29 : #define FILE_HANDLE_OFFSET 0x1000
30 :
31 : static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
32 : struct smb_filename **_smb_fname);
33 :
34 : /**
35 : * create new fsp to be used for file_new or a durable handle reconnect
36 : */
37 146114 : NTSTATUS fsp_new(struct connection_struct *conn, TALLOC_CTX *mem_ctx,
38 : files_struct **result)
39 : {
40 146114 : NTSTATUS status = NT_STATUS_NO_MEMORY;
41 146114 : files_struct *fsp = NULL;
42 146114 : struct smbd_server_connection *sconn = conn->sconn;
43 :
44 146114 : fsp = talloc_zero(mem_ctx, struct files_struct);
45 146114 : if (fsp == NULL) {
46 0 : goto fail;
47 : }
48 :
49 : /*
50 : * This can't be a child of fsp because the file_handle can be ref'd
51 : * when doing a dos/fcb open, which will then share the file_handle
52 : * across multiple fsps.
53 : */
54 146114 : fsp->fh = fd_handle_create(mem_ctx);
55 146114 : if (fsp->fh == NULL) {
56 0 : goto fail;
57 : }
58 :
59 146114 : fsp->fsp_flags.use_ofd_locks = !lp_smbd_force_process_locks(SNUM(conn));
60 : #ifndef HAVE_OFD_LOCKS
61 : fsp->fsp_flags.use_ofd_locks = false;
62 : #endif
63 :
64 146114 : fh_set_refcount(fsp->fh, 1);
65 146114 : fsp_set_fd(fsp, -1);
66 :
67 146114 : fsp->fnum = FNUM_FIELD_INVALID;
68 146114 : fsp->conn = conn;
69 146114 : fsp->close_write_time = make_omit_timespec();
70 :
71 146114 : DLIST_ADD(sconn->files, fsp);
72 146114 : sconn->num_files += 1;
73 :
74 146114 : conn->num_files_open++;
75 :
76 146114 : DBG_INFO("allocated files structure (%u used)\n",
77 : (unsigned int)sconn->num_files);
78 :
79 146114 : *result = fsp;
80 146114 : return NT_STATUS_OK;
81 :
82 0 : fail:
83 0 : if (fsp != NULL) {
84 0 : TALLOC_FREE(fsp->fh);
85 : }
86 0 : TALLOC_FREE(fsp);
87 :
88 0 : return status;
89 : }
90 :
91 122645 : void fsp_set_gen_id(files_struct *fsp)
92 : {
93 : static uint64_t gen_id = 1;
94 :
95 : /*
96 : * A billion of 64-bit increments per second gives us
97 : * more than 500 years of runtime without wrap.
98 : */
99 122645 : gen_id++;
100 122645 : fh_set_gen_id(fsp->fh, gen_id);
101 122645 : }
102 :
103 : /****************************************************************************
104 : Find first available file slot.
105 : ****************************************************************************/
106 :
107 20603 : NTSTATUS fsp_bind_smb(struct files_struct *fsp, struct smb_request *req)
108 : {
109 20603 : struct smbXsrv_open *op = NULL;
110 : NTTIME now;
111 : NTSTATUS status;
112 :
113 20603 : if (req == NULL) {
114 4264 : DBG_DEBUG("INTERNAL_OPEN_ONLY, skipping smbXsrv_open\n");
115 4264 : return NT_STATUS_OK;
116 : }
117 :
118 16339 : now = timeval_to_nttime(&fsp->open_time);
119 :
120 16339 : status = smbXsrv_open_create(req->xconn,
121 16339 : fsp->conn->session_info,
122 : now,
123 : &op);
124 16339 : if (!NT_STATUS_IS_OK(status)) {
125 0 : return status;
126 : }
127 16339 : fsp->op = op;
128 16339 : op->compat = fsp;
129 16339 : fsp->fnum = op->local_id;
130 :
131 16339 : fsp->mid = req->mid;
132 16339 : req->chain_fsp = fsp;
133 :
134 16339 : DBG_DEBUG("fsp [%s] mid [%" PRIu64"]\n",
135 : fsp_str_dbg(fsp), fsp->mid);
136 :
137 16339 : return NT_STATUS_OK;
138 : }
139 :
140 9445 : NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
141 : files_struct **result)
142 : {
143 9445 : struct smbd_server_connection *sconn = conn->sconn;
144 : files_struct *fsp;
145 : NTSTATUS status;
146 :
147 9445 : status = fsp_new(conn, conn, &fsp);
148 9445 : if (!NT_STATUS_IS_OK(status)) {
149 0 : return status;
150 : }
151 :
152 9445 : GetTimeOfDay(&fsp->open_time);
153 :
154 9445 : status = fsp_bind_smb(fsp, req);
155 9445 : if (!NT_STATUS_IS_OK(status)) {
156 0 : file_free(NULL, fsp);
157 0 : return status;
158 : }
159 :
160 9445 : fsp_set_gen_id(fsp);
161 :
162 : /*
163 : * Create an smb_filename with "" for the base_name. There are very
164 : * few NULL checks, so make sure it's initialized with something. to
165 : * be safe until an audit can be done.
166 : */
167 9445 : fsp->fsp_name = synthetic_smb_fname(fsp,
168 : "",
169 : NULL,
170 : NULL,
171 : 0,
172 : 0);
173 9445 : if (fsp->fsp_name == NULL) {
174 0 : file_free(NULL, fsp);
175 0 : return NT_STATUS_NO_MEMORY;
176 : }
177 :
178 9445 : DBG_INFO("new file %s\n", fsp_fnum_dbg(fsp));
179 :
180 : /* A new fsp invalidates the positive and
181 : negative fsp_fi_cache as the new fsp is pushed
182 : at the start of the list and we search from
183 : a cache hit to the *end* of the list. */
184 :
185 9445 : ZERO_STRUCT(sconn->fsp_fi_cache);
186 :
187 9445 : *result = fsp;
188 9445 : return NT_STATUS_OK;
189 : }
190 :
191 4184 : NTSTATUS create_internal_fsp(connection_struct *conn,
192 : const struct smb_filename *smb_fname,
193 : struct files_struct **_fsp)
194 : {
195 4184 : struct files_struct *fsp = NULL;
196 : NTSTATUS status;
197 :
198 4184 : status = file_new(NULL, conn, &fsp);
199 4184 : if (!NT_STATUS_IS_OK(status)) {
200 0 : return status;
201 : }
202 :
203 4184 : status = fsp_set_smb_fname(fsp, smb_fname);
204 4184 : if (!NT_STATUS_IS_OK(status)) {
205 0 : file_free(NULL, fsp);
206 0 : return status;
207 : }
208 :
209 4184 : *_fsp = fsp;
210 4184 : return NT_STATUS_OK;
211 : }
212 :
213 : /*
214 : * Create an internal fsp for an *existing* directory.
215 : *
216 : * This should only be used by callers in the VFS that need to control the
217 : * opening of the directory. Otherwise use open_internal_dirfsp_at().
218 : */
219 4184 : NTSTATUS create_internal_dirfsp(connection_struct *conn,
220 : const struct smb_filename *smb_dname,
221 : struct files_struct **_fsp)
222 : {
223 4184 : struct files_struct *fsp = NULL;
224 : NTSTATUS status;
225 :
226 4184 : status = create_internal_fsp(conn, smb_dname, &fsp);
227 4184 : if (!NT_STATUS_IS_OK(status)) {
228 0 : return status;
229 : }
230 :
231 4184 : fsp->access_mask = FILE_LIST_DIRECTORY;
232 4184 : fsp->fsp_flags.is_directory = true;
233 4184 : fsp->fsp_flags.is_dirfsp = true;
234 :
235 4184 : *_fsp = fsp;
236 4184 : return NT_STATUS_OK;
237 : }
238 :
239 : /*
240 : * Open an internal fsp for an *existing* directory.
241 : */
242 846 : NTSTATUS open_internal_dirfsp(connection_struct *conn,
243 : const struct smb_filename *smb_dname,
244 : int _open_flags,
245 : struct files_struct **_fsp)
246 : {
247 846 : struct vfs_open_how how = { .flags = _open_flags, };
248 846 : struct files_struct *fsp = NULL;
249 : NTSTATUS status;
250 :
251 846 : status = create_internal_dirfsp(conn, smb_dname, &fsp);
252 846 : if (!NT_STATUS_IS_OK(status)) {
253 0 : return status;
254 : }
255 :
256 : #ifdef O_DIRECTORY
257 846 : how.flags |= O_DIRECTORY;
258 : #endif
259 846 : status = fd_openat(conn->cwd_fsp, fsp->fsp_name, fsp, &how);
260 846 : if (!NT_STATUS_IS_OK(status)) {
261 0 : DBG_INFO("Could not open fd for %s (%s)\n",
262 : smb_fname_str_dbg(smb_dname),
263 : nt_errstr(status));
264 0 : file_free(NULL, fsp);
265 0 : return status;
266 : }
267 :
268 846 : status = vfs_stat_fsp(fsp);
269 846 : if (!NT_STATUS_IS_OK(status)) {
270 0 : file_free(NULL, fsp);
271 0 : return status;
272 : }
273 :
274 846 : if (!S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
275 0 : DBG_ERR("%s is not a directory!\n",
276 : smb_fname_str_dbg(smb_dname));
277 0 : file_free(NULL, fsp);
278 0 : return NT_STATUS_NOT_A_DIRECTORY;
279 : }
280 :
281 846 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
282 :
283 846 : *_fsp = fsp;
284 846 : return NT_STATUS_OK;
285 : }
286 :
287 : /*
288 : * Convert a pathref dirfsp into a real fsp. No need to do any cwd
289 : * tricks, we just open ".".
290 : */
291 3338 : NTSTATUS openat_internal_dir_from_pathref(
292 : struct files_struct *dirfsp,
293 : int _open_flags,
294 : struct files_struct **_fsp)
295 : {
296 3338 : struct connection_struct *conn = dirfsp->conn;
297 3338 : struct smb_filename *smb_dname = dirfsp->fsp_name;
298 3338 : struct files_struct *fsp = NULL;
299 3338 : char dot[] = ".";
300 8668 : struct smb_filename smb_dot = {
301 : .base_name = dot,
302 3338 : .flags = smb_dname->flags,
303 3338 : .twrp = smb_dname->twrp,
304 : };
305 3338 : struct vfs_open_how how = { .flags = _open_flags, };
306 : NTSTATUS status;
307 :
308 3338 : status = create_internal_dirfsp(conn, smb_dname, &fsp);
309 3338 : if (!NT_STATUS_IS_OK(status)) {
310 0 : return status;
311 : }
312 :
313 : /*
314 : * Pointless for opening ".", but you never know...
315 : */
316 3338 : how.flags |= O_NOFOLLOW;
317 :
318 3338 : status = fd_openat(dirfsp, &smb_dot, fsp, &how);
319 3338 : if (!NT_STATUS_IS_OK(status)) {
320 0 : DBG_INFO("fd_openat(\"%s\", \".\") failed: %s\n",
321 : fsp_str_dbg(dirfsp),
322 : nt_errstr(status));
323 0 : file_free(NULL, fsp);
324 0 : return status;
325 : }
326 :
327 3338 : fsp->fsp_name->st = smb_dname->st;
328 3338 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
329 3338 : *_fsp = fsp;
330 3338 : return NT_STATUS_OK;
331 : }
332 :
333 : /*
334 : * The "link" in the name doesn't imply link in the filesystem
335 : * sense. It's a object that "links" together an fsp and an smb_fname
336 : * and the link allocated as talloc child of an fsp.
337 : *
338 : * The link is created for fsps that openat_pathref_fsp() returns in
339 : * smb_fname->fsp. When this fsp is freed by file_free() by some caller
340 : * somewhere, the destructor fsp_smb_fname_link_destructor() on the link object
341 : * will use the link to reset the reference in smb_fname->fsp that is about to
342 : * go away.
343 : *
344 : * This prevents smb_fname_internal_fsp_destructor() from seeing dangling fsp
345 : * pointers.
346 : */
347 :
348 : struct fsp_smb_fname_link {
349 : struct fsp_smb_fname_link **smb_fname_link;
350 : struct files_struct **smb_fname_fsp;
351 : };
352 :
353 129169 : static int fsp_smb_fname_link_destructor(struct fsp_smb_fname_link *link)
354 : {
355 129169 : if (link->smb_fname_link == NULL) {
356 0 : return 0;
357 : }
358 :
359 129169 : *link->smb_fname_link = NULL;
360 129169 : *link->smb_fname_fsp = NULL;
361 129169 : return 0;
362 : }
363 :
364 259190 : static NTSTATUS fsp_smb_fname_link(struct files_struct *fsp,
365 : struct fsp_smb_fname_link **smb_fname_link,
366 : struct files_struct **smb_fname_fsp)
367 : {
368 259190 : struct fsp_smb_fname_link *link = NULL;
369 :
370 259190 : SMB_ASSERT(*smb_fname_link == NULL);
371 259190 : SMB_ASSERT(*smb_fname_fsp == NULL);
372 :
373 259190 : link = talloc_zero(fsp, struct fsp_smb_fname_link);
374 259190 : if (link == NULL) {
375 0 : return NT_STATUS_NO_MEMORY;
376 : }
377 :
378 259190 : link->smb_fname_link = smb_fname_link;
379 259190 : link->smb_fname_fsp = smb_fname_fsp;
380 259190 : *smb_fname_link = link;
381 259190 : *smb_fname_fsp = fsp;
382 :
383 259190 : talloc_set_destructor(link, fsp_smb_fname_link_destructor);
384 259190 : return NT_STATUS_OK;
385 : }
386 :
387 : /*
388 : * Free a link, carefully avoiding to trigger the link destructor
389 : */
390 153216 : static void destroy_fsp_smb_fname_link(struct fsp_smb_fname_link **_link)
391 : {
392 153216 : struct fsp_smb_fname_link *link = *_link;
393 :
394 153216 : if (link == NULL) {
395 23195 : return;
396 : }
397 130021 : talloc_set_destructor(link, NULL);
398 130021 : TALLOC_FREE(link);
399 130021 : *_link = NULL;
400 : }
401 :
402 : /*
403 : * Talloc destructor set on an smb_fname set by openat_pathref_fsp() used to
404 : * close the embedded smb_fname->fsp.
405 : */
406 95166 : static int smb_fname_fsp_destructor(struct smb_filename *smb_fname)
407 : {
408 95166 : struct files_struct *fsp = smb_fname->fsp;
409 : NTSTATUS status;
410 95166 : int saved_errno = errno;
411 :
412 95166 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
413 :
414 95166 : if (fsp == NULL) {
415 2 : errno = saved_errno;
416 2 : return 0;
417 : }
418 :
419 95164 : if (fsp_is_alternate_stream(fsp)) {
420 16 : struct files_struct *tmp_base_fsp = fsp->base_fsp;
421 :
422 16 : fsp_set_base_fsp(fsp, NULL);
423 :
424 16 : status = fd_close(tmp_base_fsp);
425 16 : if (!NT_STATUS_IS_OK(status)) {
426 0 : DBG_ERR("Closing fd for fsp [%s] failed: %s. "
427 : "Please check your filesystem!!!\n",
428 : fsp_str_dbg(fsp), nt_errstr(status));
429 : }
430 16 : file_free(NULL, tmp_base_fsp);
431 : }
432 :
433 95164 : status = fd_close(fsp);
434 95164 : if (!NT_STATUS_IS_OK(status)) {
435 0 : DBG_ERR("Closing fd for fsp [%s] failed: %s. "
436 : "Please check your filesystem!!!\n",
437 : fsp_str_dbg(fsp), nt_errstr(status));
438 : }
439 95164 : file_free(NULL, fsp);
440 95164 : smb_fname->fsp = NULL;
441 :
442 95164 : errno = saved_errno;
443 95164 : return 0;
444 : }
445 :
446 113200 : static NTSTATUS openat_pathref_fullname(
447 : struct connection_struct *conn,
448 : const struct files_struct *dirfsp,
449 : struct files_struct *basefsp,
450 : struct smb_filename **full_fname,
451 : struct smb_filename *smb_fname,
452 : const struct vfs_open_how *how)
453 : {
454 113200 : struct files_struct *fsp = NULL;
455 113200 : bool have_dirfsp = (dirfsp != NULL);
456 113200 : bool have_basefsp = (basefsp != NULL);
457 : NTSTATUS status;
458 :
459 113200 : DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
460 :
461 113200 : SMB_ASSERT(smb_fname->fsp == NULL);
462 113200 : SMB_ASSERT(have_dirfsp != have_basefsp);
463 :
464 113200 : status = fsp_new(conn, conn, &fsp);
465 113200 : if (!NT_STATUS_IS_OK(status)) {
466 0 : return status;
467 : }
468 :
469 113200 : GetTimeOfDay(&fsp->open_time);
470 113200 : fsp_set_gen_id(fsp);
471 113200 : ZERO_STRUCT(conn->sconn->fsp_fi_cache);
472 :
473 113200 : fsp->fsp_flags.is_pathref = true;
474 :
475 113200 : status = fsp_attach_smb_fname(fsp, full_fname);
476 113200 : if (!NT_STATUS_IS_OK(status)) {
477 0 : goto fail;
478 : }
479 113200 : fsp_set_base_fsp(fsp, basefsp);
480 :
481 113200 : status = fd_openat(dirfsp, smb_fname, fsp, how);
482 113200 : if (!NT_STATUS_IS_OK(status)) {
483 :
484 13326 : smb_fname->st = fsp->fsp_name->st;
485 :
486 21752 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) ||
487 21748 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
488 13322 : NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK))
489 : {
490 : /*
491 : * streams_xattr return NT_STATUS_NOT_FOUND for
492 : * opens of not yet existing streams.
493 : *
494 : * ELOOP maps to NT_STATUS_OBJECT_PATH_NOT_FOUND
495 : * and this will result from a open request from
496 : * a POSIX client on a symlink.
497 : *
498 : * NT_STATUS_OBJECT_NAME_NOT_FOUND is the simple
499 : * ENOENT case.
500 : *
501 : * NT_STATUS_STOPPED_ON_SYMLINK is returned when trying
502 : * to open a symlink, our callers are not interested in
503 : * this.
504 : */
505 20 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
506 : }
507 13326 : goto fail;
508 : }
509 :
510 : /*
511 : * fd_openat() has done an FSTAT on the handle
512 : * so update the smb_fname stat info with "truth".
513 : * from the handle.
514 : */
515 99874 : smb_fname->st = fsp->fsp_name->st;
516 :
517 99874 : fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
518 :
519 99874 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
520 :
521 99874 : status = fsp_smb_fname_link(fsp,
522 : &smb_fname->fsp_link,
523 : &smb_fname->fsp);
524 99874 : if (!NT_STATUS_IS_OK(status)) {
525 0 : goto fail;
526 : }
527 :
528 99874 : DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp));
529 :
530 99874 : talloc_set_destructor(smb_fname, smb_fname_fsp_destructor);
531 99874 : return NT_STATUS_OK;
532 :
533 13326 : fail:
534 13326 : DBG_DEBUG("Opening pathref for [%s] failed: %s\n",
535 : smb_fname_str_dbg(smb_fname),
536 : nt_errstr(status));
537 :
538 13326 : fsp_set_base_fsp(fsp, NULL);
539 13326 : fd_close(fsp);
540 13326 : file_free(NULL, fsp);
541 13326 : return status;
542 : }
543 :
544 : /*
545 : * Open an internal O_PATH based fsp for smb_fname. If O_PATH is not
546 : * available, open O_RDONLY as root. Both is done in fd_open() ->
547 : * non_widelink_open(), triggered by setting fsp->fsp_flags.is_pathref to
548 : * true.
549 : */
550 113128 : NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
551 : struct smb_filename *smb_fname)
552 : {
553 113128 : connection_struct *conn = dirfsp->conn;
554 113128 : struct smb_filename *full_fname = NULL;
555 113128 : struct smb_filename *base_fname = NULL;
556 113128 : struct vfs_open_how how = { .flags = O_RDONLY|O_NONBLOCK, };
557 : NTSTATUS status;
558 :
559 113128 : DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
560 :
561 113128 : if (smb_fname->fsp != NULL) {
562 : /* We already have one for this name. */
563 0 : DBG_DEBUG("smb_fname [%s] already has a pathref fsp.\n",
564 : smb_fname_str_dbg(smb_fname));
565 0 : return NT_STATUS_OK;
566 : }
567 :
568 113144 : if (is_named_stream(smb_fname) &&
569 32 : ((conn->fs_capabilities & FILE_NAMED_STREAMS) == 0)) {
570 0 : DBG_DEBUG("stream open [%s] on non-stream share\n",
571 : smb_fname_str_dbg(smb_fname));
572 0 : return NT_STATUS_OBJECT_NAME_INVALID;
573 : }
574 :
575 113128 : if (!is_named_stream(smb_fname)) {
576 : /*
577 : * openat_pathref_fullname() will make "full_fname" a
578 : * talloc child of the smb_fname->fsp. Don't use
579 : * talloc_tos() to allocate it to avoid making the
580 : * talloc stackframe pool long-lived.
581 : */
582 113096 : full_fname = full_path_from_dirfsp_atname(
583 : conn,
584 : dirfsp,
585 : smb_fname);
586 113096 : if (full_fname == NULL) {
587 0 : status = NT_STATUS_NO_MEMORY;
588 0 : goto fail;
589 : }
590 113096 : status = openat_pathref_fullname(
591 : conn, dirfsp, NULL, &full_fname, smb_fname, &how);
592 113096 : TALLOC_FREE(full_fname);
593 113096 : return status;
594 : }
595 :
596 : /*
597 : * stream open
598 : */
599 32 : base_fname = cp_smb_filename_nostream(conn, smb_fname);
600 32 : if (base_fname == NULL) {
601 0 : return NT_STATUS_NO_MEMORY;
602 : }
603 :
604 32 : full_fname = full_path_from_dirfsp_atname(
605 : conn, /* no talloc_tos(), see comment above */
606 : dirfsp,
607 : base_fname);
608 32 : if (full_fname == NULL) {
609 0 : status = NT_STATUS_NO_MEMORY;
610 0 : goto fail;
611 : }
612 :
613 32 : status = openat_pathref_fullname(
614 : conn, dirfsp, NULL, &full_fname, base_fname, &how);
615 32 : TALLOC_FREE(full_fname);
616 32 : if (!NT_STATUS_IS_OK(status)) {
617 0 : DBG_DEBUG("openat_pathref_nostream failed: %s\n",
618 : nt_errstr(status));
619 0 : goto fail;
620 : }
621 :
622 32 : status = open_stream_pathref_fsp(&base_fname->fsp, smb_fname);
623 32 : if (!NT_STATUS_IS_OK(status)) {
624 0 : DBG_DEBUG("open_stream_pathref_fsp failed: %s\n",
625 : nt_errstr(status));
626 0 : goto fail;
627 : }
628 :
629 32 : smb_fname_fsp_unlink(base_fname);
630 32 : fail:
631 32 : TALLOC_FREE(base_fname);
632 32 : return status;
633 : }
634 :
635 : /*
636 : * Open a stream given an already opened base_fsp. Avoid
637 : * non_widelink_open: This is only valid for the case where we have a
638 : * valid non-cwd_fsp dirfsp that we can pass to SMB_VFS_OPENAT()
639 : */
640 72 : NTSTATUS open_stream_pathref_fsp(
641 : struct files_struct **_base_fsp,
642 : struct smb_filename *smb_fname)
643 : {
644 72 : struct files_struct *base_fsp = *_base_fsp;
645 72 : connection_struct *conn = base_fsp->conn;
646 72 : struct smb_filename *base_fname = base_fsp->fsp_name;
647 72 : struct smb_filename *full_fname = NULL;
648 72 : struct vfs_open_how how = { .flags = O_RDONLY|O_NONBLOCK, };
649 : NTSTATUS status;
650 :
651 72 : SMB_ASSERT(smb_fname->fsp == NULL);
652 72 : SMB_ASSERT(is_named_stream(smb_fname));
653 :
654 144 : full_fname = synthetic_smb_fname(
655 : conn, /* no talloc_tos(), this will be long-lived */
656 72 : base_fname->base_name,
657 72 : smb_fname->stream_name,
658 72 : &smb_fname->st,
659 : smb_fname->twrp,
660 : smb_fname->flags);
661 72 : if (full_fname == NULL) {
662 0 : return NT_STATUS_NO_MEMORY;
663 : }
664 :
665 72 : status = openat_pathref_fullname(
666 : conn, NULL, base_fsp, &full_fname, smb_fname, &how);
667 72 : TALLOC_FREE(full_fname);
668 72 : return status;
669 : }
670 :
671 19443 : static char *path_to_strv(TALLOC_CTX *mem_ctx, const char *path)
672 : {
673 19443 : char *result = talloc_strdup(mem_ctx, path);
674 :
675 19443 : if (result == NULL) {
676 0 : return NULL;
677 : }
678 19443 : string_replace(result, '/', '\0');
679 19443 : return result;
680 : }
681 :
682 12870 : static NTSTATUS readlink_talloc(
683 : TALLOC_CTX *mem_ctx,
684 : struct files_struct *dirfsp,
685 : struct smb_filename *smb_relname,
686 : char **_substitute)
687 : {
688 : char buf[4096];
689 : ssize_t ret;
690 : char *substitute;
691 : NTSTATUS status;
692 :
693 12870 : if (_substitute == NULL) {
694 0 : return NT_STATUS_OK;
695 : }
696 :
697 12870 : if (smb_relname == NULL) {
698 : /*
699 : * We have a Linux O_PATH handle in dirfsp and want to
700 : * read its value, essentially a freadlink
701 : */
702 0 : smb_relname = synthetic_smb_fname(
703 : talloc_tos(), "", NULL, NULL, 0, 0);
704 0 : if (smb_relname == NULL) {
705 0 : DBG_DEBUG("synthetic_smb_fname() failed\n");
706 0 : return NT_STATUS_NO_MEMORY;
707 : }
708 : }
709 :
710 12870 : ret = SMB_VFS_READLINKAT(
711 : dirfsp->conn, dirfsp, smb_relname, buf, sizeof(buf));
712 12870 : if (ret < 0) {
713 0 : status = map_nt_error_from_unix(errno);
714 0 : DBG_DEBUG("SMB_VFS_READLINKAT() failed: %s\n",
715 : strerror(errno));
716 0 : return status;
717 : }
718 :
719 12870 : if ((size_t)ret == sizeof(buf)) {
720 : /*
721 : * Do we need symlink targets >4k?
722 : */
723 0 : DBG_DEBUG("Got full %zu bytes from readlink, too long\n",
724 : sizeof(buf));
725 0 : return NT_STATUS_BUFFER_OVERFLOW;
726 : }
727 :
728 12870 : substitute = talloc_strndup(mem_ctx, buf, ret);
729 12870 : if (substitute == NULL) {
730 0 : DBG_DEBUG("talloc_strndup() failed\n");
731 0 : return NT_STATUS_NO_MEMORY;
732 : }
733 :
734 12870 : *_substitute = substitute;
735 12870 : return NT_STATUS_OK;
736 : }
737 :
738 19443 : NTSTATUS openat_pathref_dirfsp_nosymlink(
739 : TALLOC_CTX *mem_ctx,
740 : struct connection_struct *conn,
741 : const char *path_in,
742 : NTTIME twrp,
743 : struct smb_filename **_smb_fname,
744 : size_t *unparsed,
745 : char **substitute)
746 : {
747 19443 : struct files_struct *dirfsp = conn->cwd_fsp;
748 19443 : struct smb_filename full_fname = {
749 : .base_name = NULL,
750 : .twrp = twrp,
751 : };
752 19443 : struct smb_filename rel_fname = {
753 : .base_name = NULL,
754 : .twrp = twrp,
755 : };
756 19443 : struct smb_filename *result = NULL;
757 19443 : struct files_struct *fsp = NULL;
758 19443 : char *path = NULL, *next = NULL;
759 : int fd;
760 : NTSTATUS status;
761 19443 : struct vfs_open_how how = {
762 : .flags = O_NOFOLLOW|O_DIRECTORY,
763 : .mode = 0,
764 : };
765 :
766 19443 : DBG_DEBUG("path_in=%s\n", path_in);
767 :
768 19443 : status = fsp_new(conn, conn, &fsp);
769 19443 : if (!NT_STATUS_IS_OK(status)) {
770 0 : DBG_DEBUG("fsp_new() failed: %s\n", nt_errstr(status));
771 0 : goto fail;
772 : }
773 19443 : fsp->fsp_name = &full_fname;
774 :
775 : #ifdef O_PATH
776 : /*
777 : * Add O_PATH manually, doing this by setting
778 : * fsp->fsp_flags.is_pathref will make us become_root() in the
779 : * non-O_PATH case, which would cause a security problem.
780 : */
781 19443 : how.flags |= O_PATH;
782 : #else
783 : #ifdef O_SEARCH
784 : /*
785 : * O_SEARCH just checks for the "x" bit. We are traversing
786 : * directories, so we don't need the implicit O_RDONLY ("r"
787 : * permissions) but only the "x"-permissions requested by
788 : * O_SEARCH. We need either O_PATH or O_SEARCH to correctly
789 : * function, without either we will incorrectly require also
790 : * the "r" bit when traversing the directory hierarchy.
791 : */
792 : how.flags |= O_SEARCH;
793 : #endif
794 : #endif
795 :
796 19443 : full_fname.base_name = talloc_strdup(talloc_tos(), "");
797 19443 : if (full_fname.base_name == NULL) {
798 0 : DBG_DEBUG("talloc_strdup() failed\n");
799 0 : goto nomem;
800 : }
801 :
802 : /*
803 : * First split the path into individual components.
804 : */
805 19443 : path = path_to_strv(talloc_tos(), path_in);
806 19443 : if (path == NULL) {
807 0 : DBG_DEBUG("path_to_strv() failed\n");
808 0 : goto nomem;
809 : }
810 :
811 : /*
812 : * First we loop over all components
813 : * in order to verify, there's no '.' or '..'
814 : */
815 19443 : rel_fname.base_name = path;
816 235843 : while (rel_fname.base_name != NULL) {
817 :
818 203667 : next = strv_next(path, rel_fname.base_name);
819 :
820 : /*
821 : * Path sanitizing further up has cleaned or rejected
822 : * empty path components. Assert this here.
823 : */
824 203667 : SMB_ASSERT(rel_fname.base_name[0] != '\0');
825 :
826 203667 : if (ISDOT(rel_fname.base_name) || ISDOTDOT(rel_fname.base_name)) {
827 0 : DBG_DEBUG("%s contains a dot\n", path_in);
828 0 : status = NT_STATUS_OBJECT_NAME_INVALID;
829 0 : goto fail;
830 : }
831 :
832 : /* Check veto files. */
833 203667 : if (IS_VETO_PATH(conn, rel_fname.base_name)) {
834 0 : DBG_DEBUG("%s contains veto files path component %s\n",
835 : path_in, rel_fname.base_name);
836 0 : status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
837 0 : goto fail;
838 : }
839 :
840 203667 : rel_fname.base_name = next;
841 : }
842 :
843 19443 : if (conn->open_how_resolve & VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS) {
844 :
845 : /*
846 : * Try a direct openat2 with RESOLVE_NO_SYMLINKS to
847 : * avoid the openat/close loop further down.
848 : */
849 :
850 19386 : rel_fname.base_name = discard_const_p(char, path_in);
851 19386 : how.resolve = VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS;
852 :
853 19386 : fd = SMB_VFS_OPENAT(conn, dirfsp, &rel_fname, fsp, &how);
854 19386 : if (fd >= 0) {
855 5938 : fsp_set_fd(fsp, fd);
856 5938 : TALLOC_FREE(full_fname.base_name);
857 5938 : full_fname = rel_fname;
858 5938 : goto done;
859 : }
860 :
861 13448 : status = map_nt_error_from_unix(errno);
862 13448 : DBG_DEBUG("SMB_VFS_OPENAT(%s, %s, RESOLVE_NO_SYMLINKS) returned %d %s => %s\n",
863 : smb_fname_str_dbg(dirfsp->fsp_name), path_in,
864 : errno, strerror(errno), nt_errstr(status));
865 13448 : SMB_ASSERT(fd == -1);
866 13448 : switch (errno) {
867 0 : case ENOSYS:
868 : /*
869 : * We got ENOSYS, so fallback to the old code
870 : * if the kernel doesn't support openat2() yet.
871 : */
872 0 : break;
873 :
874 12870 : case ELOOP:
875 : case ENOTDIR:
876 : /*
877 : * For ELOOP we also fallback in order to
878 : * return the correct information with
879 : * NT_STATUS_STOPPED_ON_SYMLINK.
880 : *
881 : * O_NOFOLLOW|O_DIRECTORY results in
882 : * ENOTDIR instead of ELOOP for the final
883 : * component.
884 : */
885 12870 : break;
886 :
887 578 : case ENOENT:
888 : /*
889 : * If we got ENOENT, the filesystem could
890 : * be case sensitive. For now we only do
891 : * the get_real_filename_at() dance in
892 : * the fallback loop below.
893 : */
894 578 : break;
895 :
896 0 : default:
897 0 : goto fail;
898 : }
899 :
900 : /*
901 : * Just fallback to the openat loop
902 : */
903 13448 : how.resolve = 0;
904 : }
905 :
906 : /*
907 : * Now we loop over all components
908 : * opening each one and using it
909 : * as dirfd for the next one.
910 : *
911 : * It means we can detect symlinks
912 : * within the path.
913 : */
914 13505 : rel_fname.base_name = path;
915 19865 : next:
916 19865 : next = strv_next(path, rel_fname.base_name);
917 :
918 19865 : fd = SMB_VFS_OPENAT(
919 : conn,
920 : dirfsp,
921 : &rel_fname,
922 : fsp,
923 : &how);
924 :
925 19865 : if ((fd == -1) && (errno == ENOENT)) {
926 612 : const char *orig_base_name = rel_fname.base_name;
927 :
928 1222 : status = get_real_filename_at(
929 : dirfsp,
930 612 : rel_fname.base_name,
931 : talloc_tos(),
932 : &rel_fname.base_name);
933 :
934 612 : if (!NT_STATUS_IS_OK(status)) {
935 51 : DBG_DEBUG("get_real_filename_at failed: %s\n",
936 : nt_errstr(status));
937 51 : goto fail;
938 : }
939 :
940 : /* Name might have been demangled - check veto files. */
941 561 : if (IS_VETO_PATH(conn, rel_fname.base_name)) {
942 0 : DBG_DEBUG("%s contains veto files path component %s => %s\n",
943 : path_in, orig_base_name, rel_fname.base_name);
944 0 : status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
945 0 : goto fail;
946 : }
947 :
948 561 : fd = SMB_VFS_OPENAT(
949 : conn,
950 : dirfsp,
951 : &rel_fname,
952 : fsp,
953 : &how);
954 : }
955 :
956 : /*
957 : * O_NOFOLLOW|O_DIRECTORY results in
958 : * ENOTDIR instead of ELOOP.
959 : *
960 : * But we should be prepared to handle ELOOP too.
961 : */
962 19814 : if ((fd == -1) && (errno == ENOTDIR || errno == ELOOP)) {
963 12870 : NTSTATUS orig_status = map_nt_error_from_unix(errno);
964 :
965 12870 : status = readlink_talloc(
966 : mem_ctx, dirfsp, &rel_fname, substitute);
967 :
968 12870 : if (NT_STATUS_IS_OK(status)) {
969 : /*
970 : * readlink_talloc() found a symlink
971 : */
972 12870 : status = NT_STATUS_STOPPED_ON_SYMLINK;
973 :
974 12870 : if (unparsed != NULL) {
975 12870 : if (next == NULL) {
976 1078 : *unparsed = 0;
977 : } else {
978 11792 : size_t parsed = next - path;
979 11792 : size_t len = talloc_get_size(path);
980 11792 : *unparsed = len - parsed;
981 : }
982 : }
983 : /*
984 : * If we're on an MSDFS share, see if this is
985 : * an MSDFS link.
986 : */
987 25740 : if (lp_host_msdfs() &&
988 22296 : lp_msdfs_root(SNUM(conn)) &&
989 9426 : (substitute != NULL) &&
990 18852 : strnequal(*substitute, "msdfs:", 6) &&
991 9426 : is_msdfs_link(dirfsp, &rel_fname))
992 : {
993 9426 : status = NT_STATUS_PATH_NOT_COVERED;
994 : }
995 : } else {
996 :
997 0 : DBG_DEBUG("readlink_talloc failed: %s\n",
998 : nt_errstr(status));
999 : /*
1000 : * Restore the error status from SMB_VFS_OPENAT()
1001 : */
1002 0 : status = orig_status;
1003 : }
1004 12870 : goto fail;
1005 : }
1006 :
1007 6944 : if (fd == -1) {
1008 0 : status = map_nt_error_from_unix(errno);
1009 0 : DBG_DEBUG("SMB_VFS_OPENAT() failed: %s\n",
1010 : strerror(errno));
1011 0 : goto fail;
1012 : }
1013 6944 : fsp_set_fd(fsp, fd);
1014 :
1015 6944 : fsp->fsp_flags.is_directory = true; /* See O_DIRECTORY above */
1016 :
1017 12162 : full_fname.base_name = talloc_asprintf_append_buffer(
1018 : full_fname.base_name,
1019 : "%s%s",
1020 6944 : full_fname.base_name[0] == '\0' ? "" : "/",
1021 : rel_fname.base_name);
1022 :
1023 6944 : if (full_fname.base_name == NULL) {
1024 0 : DBG_DEBUG("talloc_asprintf_append_buffer() failed\n");
1025 0 : goto nomem;
1026 : }
1027 :
1028 6944 : if (next != NULL) {
1029 6360 : struct files_struct *tmp = NULL;
1030 :
1031 6360 : if (dirfsp != conn->cwd_fsp) {
1032 2334 : fd_close(dirfsp);
1033 : }
1034 :
1035 6360 : tmp = dirfsp;
1036 6360 : dirfsp = fsp;
1037 :
1038 6360 : if (tmp == conn->cwd_fsp) {
1039 4026 : status = fsp_new(conn, conn, &fsp);
1040 4026 : if (!NT_STATUS_IS_OK(status)) {
1041 0 : DBG_DEBUG("fsp_new() failed: %s\n",
1042 : nt_errstr(status));
1043 0 : goto fail;
1044 : }
1045 4026 : fsp->fsp_name = &full_fname;
1046 : } else {
1047 2334 : fsp = tmp;
1048 : }
1049 :
1050 6360 : rel_fname.base_name = next;
1051 :
1052 6360 : goto next;
1053 : }
1054 :
1055 584 : if (dirfsp != conn->cwd_fsp) {
1056 531 : SMB_ASSERT(fsp_get_pathref_fd(dirfsp) != -1);
1057 531 : fd_close(dirfsp);
1058 531 : dirfsp->fsp_name = NULL;
1059 531 : file_free(NULL, dirfsp);
1060 531 : dirfsp = NULL;
1061 : }
1062 :
1063 6294 : done:
1064 6522 : fsp->fsp_flags.is_pathref = true;
1065 6522 : fsp->fsp_name = NULL;
1066 :
1067 6522 : status = fsp_set_smb_fname(fsp, &full_fname);
1068 6522 : if (!NT_STATUS_IS_OK(status)) {
1069 0 : DBG_DEBUG("fsp_set_smb_fname() failed: %s\n",
1070 : nt_errstr(status));
1071 0 : goto fail;
1072 : }
1073 :
1074 6522 : status = vfs_stat_fsp(fsp);
1075 6522 : if (!NT_STATUS_IS_OK(status)) {
1076 0 : DBG_DEBUG("vfs_stat_fsp(%s) failed: %s\n",
1077 : fsp_str_dbg(fsp),
1078 : nt_errstr(status));
1079 0 : goto fail;
1080 : }
1081 : /*
1082 : * We must correctly set fsp->file_id as code inside
1083 : * open.c will use this to check if delete_on_close
1084 : * has been set on the dirfsp.
1085 : */
1086 6522 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
1087 :
1088 6522 : result = cp_smb_filename(mem_ctx, fsp->fsp_name);
1089 6522 : if (result == NULL) {
1090 0 : DBG_DEBUG("cp_smb_filename() failed\n");
1091 0 : goto nomem;
1092 : }
1093 :
1094 6522 : status = fsp_smb_fname_link(fsp,
1095 : &result->fsp_link,
1096 : &result->fsp);
1097 6522 : if (!NT_STATUS_IS_OK(status)) {
1098 0 : goto fail;
1099 : }
1100 6522 : talloc_set_destructor(result, smb_fname_fsp_destructor);
1101 :
1102 6522 : *_smb_fname = result;
1103 :
1104 6522 : DBG_DEBUG("returning %s\n", smb_fname_str_dbg(result));
1105 :
1106 6522 : return NT_STATUS_OK;
1107 :
1108 0 : nomem:
1109 0 : status = NT_STATUS_NO_MEMORY;
1110 12921 : fail:
1111 12921 : if (fsp != NULL) {
1112 12921 : if (fsp_get_pathref_fd(fsp) != -1) {
1113 0 : fd_close(fsp);
1114 : }
1115 12921 : file_free(NULL, fsp);
1116 12921 : fsp = NULL;
1117 : }
1118 :
1119 12921 : if ((dirfsp != NULL) && (dirfsp != conn->cwd_fsp)) {
1120 3495 : SMB_ASSERT(fsp_get_pathref_fd(dirfsp) != -1);
1121 3495 : fd_close(dirfsp);
1122 3495 : dirfsp->fsp_name = NULL;
1123 3495 : file_free(NULL, dirfsp);
1124 3495 : dirfsp = NULL;
1125 : }
1126 :
1127 12921 : TALLOC_FREE(path);
1128 12921 : return status;
1129 : }
1130 :
1131 56674 : void smb_fname_fsp_unlink(struct smb_filename *smb_fname)
1132 : {
1133 56674 : talloc_set_destructor(smb_fname, NULL);
1134 56674 : smb_fname->fsp = NULL;
1135 56674 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
1136 56674 : }
1137 :
1138 : /*
1139 : * Move any existing embedded fsp refs from the src name to the
1140 : * destination. It's safe to call this on src smb_fname's that have no embedded
1141 : * pathref fsp.
1142 : */
1143 22279 : NTSTATUS move_smb_fname_fsp_link(struct smb_filename *smb_fname_dst,
1144 : struct smb_filename *smb_fname_src)
1145 : {
1146 : NTSTATUS status;
1147 :
1148 : /*
1149 : * The target should always not be linked yet!
1150 : */
1151 22279 : SMB_ASSERT(smb_fname_dst->fsp == NULL);
1152 22279 : SMB_ASSERT(smb_fname_dst->fsp_link == NULL);
1153 :
1154 22279 : if (smb_fname_src->fsp == NULL) {
1155 80 : return NT_STATUS_OK;
1156 : }
1157 :
1158 22199 : status = fsp_smb_fname_link(smb_fname_src->fsp,
1159 : &smb_fname_dst->fsp_link,
1160 : &smb_fname_dst->fsp);
1161 22199 : if (!NT_STATUS_IS_OK(status)) {
1162 0 : return status;
1163 : }
1164 :
1165 22199 : talloc_set_destructor(smb_fname_dst, smb_fname_fsp_destructor);
1166 :
1167 22199 : smb_fname_fsp_unlink(smb_fname_src);
1168 :
1169 22199 : return NT_STATUS_OK;
1170 : }
1171 :
1172 : /**
1173 : * Create an smb_fname and open smb_fname->fsp pathref
1174 : **/
1175 10473 : NTSTATUS synthetic_pathref(TALLOC_CTX *mem_ctx,
1176 : struct files_struct *dirfsp,
1177 : const char *base_name,
1178 : const char *stream_name,
1179 : const SMB_STRUCT_STAT *psbuf,
1180 : NTTIME twrp,
1181 : uint32_t flags,
1182 : struct smb_filename **_smb_fname)
1183 : {
1184 10473 : struct smb_filename *smb_fname = NULL;
1185 : NTSTATUS status;
1186 :
1187 10473 : smb_fname = synthetic_smb_fname(mem_ctx,
1188 : base_name,
1189 : stream_name,
1190 : psbuf,
1191 : twrp,
1192 : flags);
1193 10473 : if (smb_fname == NULL) {
1194 0 : return NT_STATUS_NO_MEMORY;
1195 : }
1196 :
1197 10473 : status = openat_pathref_fsp(dirfsp, smb_fname);
1198 10473 : if (!NT_STATUS_IS_OK(status)) {
1199 315 : DBG_NOTICE("opening [%s] failed\n",
1200 : smb_fname_str_dbg(smb_fname));
1201 315 : TALLOC_FREE(smb_fname);
1202 315 : return status;
1203 : }
1204 :
1205 10158 : *_smb_fname = smb_fname;
1206 10158 : return NT_STATUS_OK;
1207 : }
1208 :
1209 1376 : static int atname_destructor(struct smb_filename *smb_fname)
1210 : {
1211 1376 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
1212 1376 : return 0;
1213 : }
1214 :
1215 : /**
1216 : * Turn a path into a parent pathref and atname
1217 : *
1218 : * This returns the parent pathref in _parent and the name relative to it. If
1219 : * smb_fname was a pathref (ie smb_fname->fsp != NULL), then _atname will be a
1220 : * pathref as well, ie _atname->fsp will point at the same fsp as
1221 : * smb_fname->fsp.
1222 : **/
1223 1773 : NTSTATUS parent_pathref(TALLOC_CTX *mem_ctx,
1224 : struct files_struct *dirfsp,
1225 : const struct smb_filename *smb_fname,
1226 : struct smb_filename **_parent,
1227 : struct smb_filename **_atname)
1228 : {
1229 1773 : struct smb_filename *parent = NULL;
1230 1773 : struct smb_filename *atname = NULL;
1231 : NTSTATUS status;
1232 :
1233 1773 : status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
1234 : mem_ctx,
1235 : smb_fname,
1236 : &parent,
1237 : &atname);
1238 1773 : if (!NT_STATUS_IS_OK(status)) {
1239 0 : return status;
1240 : }
1241 :
1242 : /*
1243 : * We know that the parent name must
1244 : * exist, and the name has been canonicalized
1245 : * even if this was a POSIX pathname.
1246 : * Ensure that we follow symlinks for
1247 : * the parent. See the torture test
1248 : * POSIX-SYMLINK-PARENT for details.
1249 : */
1250 1773 : parent->flags &= ~SMB_FILENAME_POSIX_PATH;
1251 :
1252 1773 : status = openat_pathref_fsp(dirfsp, parent);
1253 1773 : if (!NT_STATUS_IS_OK(status)) {
1254 0 : TALLOC_FREE(parent);
1255 0 : return status;
1256 : }
1257 :
1258 1773 : if (smb_fname->fsp != NULL) {
1259 2609 : status = fsp_smb_fname_link(smb_fname->fsp,
1260 1376 : &atname->fsp_link,
1261 1376 : &atname->fsp);
1262 1376 : if (!NT_STATUS_IS_OK(status)) {
1263 0 : TALLOC_FREE(parent);
1264 0 : return status;
1265 : }
1266 1376 : talloc_set_destructor(atname, atname_destructor);
1267 : }
1268 1773 : *_parent = parent;
1269 1773 : *_atname = atname;
1270 1773 : return NT_STATUS_OK;
1271 : }
1272 :
1273 278 : static bool close_file_in_loop(struct files_struct *fsp,
1274 : enum file_close_type close_type)
1275 : {
1276 278 : if (fsp_is_alternate_stream(fsp)) {
1277 : /*
1278 : * This is a stream, it can't be a base
1279 : */
1280 0 : SMB_ASSERT(fsp->stream_fsp == NULL);
1281 0 : SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1282 :
1283 : /*
1284 : * Remove the base<->stream link so that
1285 : * close_file_free() does not close fsp->base_fsp as
1286 : * well. This would destroy walking the linked list of
1287 : * fsps.
1288 : */
1289 0 : fsp->base_fsp->stream_fsp = NULL;
1290 0 : fsp->base_fsp = NULL;
1291 :
1292 0 : close_file_free(NULL, &fsp, close_type);
1293 0 : return NULL;
1294 : }
1295 :
1296 278 : if (fsp->stream_fsp != NULL) {
1297 : /*
1298 : * This is the base of a stream.
1299 : */
1300 0 : SMB_ASSERT(fsp->stream_fsp->base_fsp == fsp);
1301 :
1302 : /*
1303 : * Remove the base<->stream link. This will make fsp
1304 : * look like a normal fsp for the next round.
1305 : */
1306 0 : fsp->stream_fsp->base_fsp = NULL;
1307 0 : fsp->stream_fsp = NULL;
1308 :
1309 : /*
1310 : * Have us called back a second time. In the second
1311 : * round, "fsp" now looks like a normal fsp.
1312 : */
1313 0 : return false;
1314 : }
1315 :
1316 278 : close_file_free(NULL, &fsp, close_type);
1317 278 : return true;
1318 : }
1319 :
1320 : /****************************************************************************
1321 : Close all open files for a connection.
1322 : ****************************************************************************/
1323 :
1324 : struct file_close_conn_state {
1325 : struct connection_struct *conn;
1326 : enum file_close_type close_type;
1327 : bool fsp_left_behind;
1328 : };
1329 :
1330 4 : static struct files_struct *file_close_conn_fn(
1331 : struct files_struct *fsp,
1332 : void *private_data)
1333 : {
1334 4 : struct file_close_conn_state *state = private_data;
1335 : bool did_close;
1336 :
1337 4 : if (fsp->conn != state->conn) {
1338 2 : return NULL;
1339 : }
1340 :
1341 2 : if (fsp->op != NULL && fsp->op->global->durable) {
1342 : /*
1343 : * A tree disconnect closes a durable handle
1344 : */
1345 0 : fsp->op->global->durable = false;
1346 : }
1347 :
1348 2 : did_close = close_file_in_loop(fsp, state->close_type);
1349 2 : if (!did_close) {
1350 0 : state->fsp_left_behind = true;
1351 : }
1352 :
1353 2 : return NULL;
1354 : }
1355 :
1356 5623 : void file_close_conn(connection_struct *conn, enum file_close_type close_type)
1357 : {
1358 5623 : struct file_close_conn_state state = { .conn = conn,
1359 : .close_type = close_type };
1360 :
1361 5623 : files_forall(conn->sconn, file_close_conn_fn, &state);
1362 :
1363 5623 : if (state.fsp_left_behind) {
1364 0 : state.fsp_left_behind = false;
1365 0 : files_forall(conn->sconn, file_close_conn_fn, &state);
1366 0 : SMB_ASSERT(!state.fsp_left_behind);
1367 : }
1368 5623 : }
1369 :
1370 : /****************************************************************************
1371 : Initialise file structures.
1372 : ****************************************************************************/
1373 :
1374 : static int files_max_open_fds;
1375 :
1376 5309 : bool file_init_global(void)
1377 : {
1378 5309 : int request_max = lp_max_open_files();
1379 : int real_lim;
1380 : int real_max;
1381 :
1382 5309 : if (files_max_open_fds != 0) {
1383 5270 : return true;
1384 : }
1385 :
1386 : /*
1387 : * Set the max_open files to be the requested
1388 : * max plus a fudgefactor to allow for the extra
1389 : * fd's we need such as log files etc...
1390 : */
1391 39 : real_lim = set_maxfiles(request_max + MAX_OPEN_FUDGEFACTOR);
1392 :
1393 39 : real_max = real_lim - MAX_OPEN_FUDGEFACTOR;
1394 :
1395 39 : if (real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) {
1396 0 : real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
1397 : }
1398 :
1399 39 : if (real_max != request_max) {
1400 0 : DEBUG(1, ("file_init_global: Information only: requested %d "
1401 : "open files, %d are available.\n",
1402 : request_max, real_max));
1403 : }
1404 :
1405 39 : SMB_ASSERT(real_max > 100);
1406 :
1407 39 : files_max_open_fds = real_max;
1408 39 : return true;
1409 : }
1410 :
1411 5270 : bool file_init(struct smbd_server_connection *sconn)
1412 : {
1413 : bool ok;
1414 :
1415 5270 : ok = file_init_global();
1416 5270 : if (!ok) {
1417 0 : return false;
1418 : }
1419 :
1420 5270 : sconn->real_max_open_files = files_max_open_fds;
1421 :
1422 5270 : return true;
1423 : }
1424 :
1425 : /****************************************************************************
1426 : Close files open by a specified vuid.
1427 : ****************************************************************************/
1428 :
1429 : struct file_close_user_state {
1430 : uint64_t vuid;
1431 : bool fsp_left_behind;
1432 : };
1433 :
1434 280 : static struct files_struct *file_close_user_fn(
1435 : struct files_struct *fsp,
1436 : void *private_data)
1437 : {
1438 280 : struct file_close_user_state *state = private_data;
1439 : bool did_close;
1440 :
1441 280 : if (fsp->vuid != state->vuid) {
1442 4 : return NULL;
1443 : }
1444 :
1445 276 : did_close = close_file_in_loop(fsp, SHUTDOWN_CLOSE);
1446 276 : if (!did_close) {
1447 0 : state->fsp_left_behind = true;
1448 : }
1449 :
1450 276 : return NULL;
1451 : }
1452 :
1453 4958 : void file_close_user(struct smbd_server_connection *sconn, uint64_t vuid)
1454 : {
1455 4958 : struct file_close_user_state state = { .vuid = vuid };
1456 :
1457 4958 : files_forall(sconn, file_close_user_fn, &state);
1458 :
1459 4958 : if (state.fsp_left_behind) {
1460 0 : state.fsp_left_behind = false;
1461 0 : files_forall(sconn, file_close_user_fn, &state);
1462 0 : SMB_ASSERT(!state.fsp_left_behind);
1463 : }
1464 4958 : }
1465 :
1466 : /*
1467 : * Walk the files table until "fn" returns non-NULL
1468 : */
1469 :
1470 12000 : struct files_struct *files_forall(
1471 : struct smbd_server_connection *sconn,
1472 : struct files_struct *(*fn)(struct files_struct *fsp,
1473 : void *private_data),
1474 : void *private_data)
1475 : {
1476 : struct files_struct *fsp, *next;
1477 :
1478 13192 : for (fsp = sconn->files; fsp; fsp = next) {
1479 : struct files_struct *ret;
1480 1244 : next = fsp->next;
1481 1244 : ret = fn(fsp, private_data);
1482 1244 : if (ret != NULL) {
1483 52 : return ret;
1484 : }
1485 : }
1486 11948 : return NULL;
1487 : }
1488 :
1489 : /****************************************************************************
1490 : Find a fsp given a file descriptor.
1491 : ****************************************************************************/
1492 :
1493 0 : files_struct *file_find_fd(struct smbd_server_connection *sconn, int fd)
1494 : {
1495 0 : int count=0;
1496 : files_struct *fsp;
1497 :
1498 0 : for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
1499 0 : if (fsp_get_pathref_fd(fsp) == fd) {
1500 0 : if (count > 10) {
1501 0 : DLIST_PROMOTE(sconn->files, fsp);
1502 : }
1503 0 : return fsp;
1504 : }
1505 : }
1506 :
1507 0 : return NULL;
1508 : }
1509 :
1510 : /****************************************************************************
1511 : Find a fsp given a device, inode and file_id.
1512 : ****************************************************************************/
1513 :
1514 20 : files_struct *file_find_dif(struct smbd_server_connection *sconn,
1515 : struct file_id id, unsigned long gen_id)
1516 : {
1517 20 : int count=0;
1518 : files_struct *fsp;
1519 :
1520 20 : if (gen_id == 0) {
1521 0 : return NULL;
1522 : }
1523 :
1524 66 : for (fsp = sconn->files; fsp; fsp = fsp->next,count++) {
1525 : /*
1526 : * We can have a fsp->fh->fd == -1 here as it could be a stat
1527 : * open.
1528 : */
1529 66 : if (!file_id_equal(&fsp->file_id, &id)) {
1530 26 : continue;
1531 : }
1532 40 : if (!fsp->fsp_flags.is_fsa) {
1533 20 : continue;
1534 : }
1535 20 : if (fh_get_gen_id(fsp->fh) != gen_id) {
1536 0 : continue;
1537 : }
1538 20 : if (count > 10) {
1539 0 : DLIST_PROMOTE(sconn->files, fsp);
1540 : }
1541 : /* Paranoia check. */
1542 20 : if ((fsp_get_pathref_fd(fsp) == -1) &&
1543 0 : (fsp->oplock_type != NO_OPLOCK &&
1544 0 : fsp->oplock_type != LEASE_OPLOCK))
1545 : {
1546 : struct file_id_buf idbuf;
1547 :
1548 0 : DBG_ERR("file %s file_id = "
1549 : "%s, gen = %u oplock_type = %u is a "
1550 : "stat open with oplock type !\n",
1551 : fsp_str_dbg(fsp),
1552 : file_id_str_buf(fsp->file_id, &idbuf),
1553 : (unsigned int)fh_get_gen_id(fsp->fh),
1554 : (unsigned int)fsp->oplock_type);
1555 0 : smb_panic("file_find_dif");
1556 : }
1557 20 : return fsp;
1558 : }
1559 :
1560 0 : return NULL;
1561 : }
1562 :
1563 : /****************************************************************************
1564 : Find the first fsp given a device and inode.
1565 : We use a singleton cache here to speed up searching from getfilepathinfo
1566 : calls.
1567 : ****************************************************************************/
1568 :
1569 41 : files_struct *file_find_di_first(struct smbd_server_connection *sconn,
1570 : struct file_id id,
1571 : bool need_fsa)
1572 : {
1573 : files_struct *fsp;
1574 :
1575 41 : if (file_id_equal(&sconn->fsp_fi_cache.id, &id)) {
1576 : /* Positive or negative cache hit. */
1577 0 : return sconn->fsp_fi_cache.fsp;
1578 : }
1579 :
1580 41 : sconn->fsp_fi_cache.id = id;
1581 :
1582 128 : for (fsp=sconn->files;fsp;fsp=fsp->next) {
1583 107 : if (need_fsa && !fsp->fsp_flags.is_fsa) {
1584 22 : continue;
1585 : }
1586 85 : if (file_id_equal(&fsp->file_id, &id)) {
1587 : /* Setup positive cache. */
1588 20 : sconn->fsp_fi_cache.fsp = fsp;
1589 20 : return fsp;
1590 : }
1591 : }
1592 :
1593 : /* Setup negative cache. */
1594 21 : sconn->fsp_fi_cache.fsp = NULL;
1595 21 : return NULL;
1596 : }
1597 :
1598 : /****************************************************************************
1599 : Find the next fsp having the same device and inode.
1600 : ****************************************************************************/
1601 :
1602 20 : files_struct *file_find_di_next(files_struct *start_fsp,
1603 : bool need_fsa)
1604 : {
1605 : files_struct *fsp;
1606 :
1607 20 : for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
1608 0 : if (need_fsa && !fsp->fsp_flags.is_fsa) {
1609 0 : continue;
1610 : }
1611 0 : if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
1612 0 : return fsp;
1613 : }
1614 : }
1615 :
1616 20 : return NULL;
1617 : }
1618 :
1619 0 : struct files_struct *file_find_one_fsp_from_lease_key(
1620 : struct smbd_server_connection *sconn,
1621 : const struct smb2_lease_key *lease_key)
1622 : {
1623 : struct files_struct *fsp;
1624 :
1625 0 : for (fsp = sconn->files; fsp; fsp=fsp->next) {
1626 0 : if ((fsp->lease != NULL) &&
1627 0 : (fsp->lease->lease.lease_key.data[0] ==
1628 0 : lease_key->data[0]) &&
1629 0 : (fsp->lease->lease.lease_key.data[1] ==
1630 0 : lease_key->data[1])) {
1631 0 : return fsp;
1632 : }
1633 : }
1634 0 : return NULL;
1635 : }
1636 :
1637 : /****************************************************************************
1638 : Find any fsp open with a pathname below that of an already open path.
1639 : ****************************************************************************/
1640 :
1641 0 : bool file_find_subpath(files_struct *dir_fsp)
1642 : {
1643 : files_struct *fsp;
1644 : size_t dlen;
1645 0 : char *d_fullname = NULL;
1646 :
1647 0 : d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
1648 0 : dir_fsp->conn->connectpath,
1649 0 : dir_fsp->fsp_name->base_name);
1650 :
1651 0 : if (!d_fullname) {
1652 0 : return false;
1653 : }
1654 :
1655 0 : dlen = strlen(d_fullname);
1656 :
1657 0 : for (fsp=dir_fsp->conn->sconn->files; fsp; fsp=fsp->next) {
1658 : char *d1_fullname;
1659 :
1660 0 : if (fsp == dir_fsp) {
1661 0 : continue;
1662 : }
1663 :
1664 0 : d1_fullname = talloc_asprintf(talloc_tos(),
1665 : "%s/%s",
1666 0 : fsp->conn->connectpath,
1667 0 : fsp->fsp_name->base_name);
1668 :
1669 : /*
1670 : * If the open file has a path that is a longer
1671 : * component, then it's a subpath.
1672 : */
1673 0 : if (strnequal(d_fullname, d1_fullname, dlen) &&
1674 0 : (d1_fullname[dlen] == '/')) {
1675 0 : TALLOC_FREE(d1_fullname);
1676 0 : TALLOC_FREE(d_fullname);
1677 0 : return true;
1678 : }
1679 0 : TALLOC_FREE(d1_fullname);
1680 : }
1681 :
1682 0 : TALLOC_FREE(d_fullname);
1683 0 : return false;
1684 : }
1685 :
1686 : /****************************************************************************
1687 : Free up a fsp.
1688 : ****************************************************************************/
1689 :
1690 146114 : static void fsp_free(files_struct *fsp)
1691 : {
1692 146114 : struct smbd_server_connection *sconn = fsp->conn->sconn;
1693 :
1694 146114 : if (fsp == sconn->fsp_fi_cache.fsp) {
1695 4 : ZERO_STRUCT(sconn->fsp_fi_cache);
1696 : }
1697 :
1698 146114 : DLIST_REMOVE(sconn->files, fsp);
1699 146114 : SMB_ASSERT(sconn->num_files > 0);
1700 146114 : sconn->num_files--;
1701 :
1702 146114 : TALLOC_FREE(fsp->fake_file_handle);
1703 :
1704 146114 : if (fh_get_refcount(fsp->fh) == 1) {
1705 146114 : TALLOC_FREE(fsp->fh);
1706 : } else {
1707 0 : size_t new_refcount = fh_get_refcount(fsp->fh) - 1;
1708 0 : fh_set_refcount(fsp->fh, new_refcount);
1709 : }
1710 :
1711 146114 : if (fsp->lease != NULL) {
1712 0 : if (fsp->lease->ref_count == 1) {
1713 0 : TALLOC_FREE(fsp->lease);
1714 : } else {
1715 0 : fsp->lease->ref_count--;
1716 : }
1717 : }
1718 :
1719 146114 : fsp->conn->num_files_open--;
1720 :
1721 252684 : if (fsp->fsp_name != NULL &&
1722 142088 : fsp->fsp_name->fsp_link != NULL)
1723 : {
1724 : /*
1725 : * Free fsp_link of fsp->fsp_name. To do this in the correct
1726 : * talloc destructor order we have to do it here. The
1727 : * talloc_free() of the link should set the fsp pointer to NULL.
1728 : */
1729 129167 : TALLOC_FREE(fsp->fsp_name->fsp_link);
1730 129167 : SMB_ASSERT(fsp->fsp_name->fsp == NULL);
1731 : }
1732 :
1733 : /* this is paranoia, just in case someone tries to reuse the
1734 : information */
1735 146114 : ZERO_STRUCTP(fsp);
1736 :
1737 : /* fsp->fsp_name is a talloc child and is free'd automatically. */
1738 146114 : TALLOC_FREE(fsp);
1739 146114 : }
1740 :
1741 : /*
1742 : * Rundown of all smb-related sub-structures of an fsp
1743 : */
1744 162530 : void fsp_unbind_smb(struct smb_request *req, files_struct *fsp)
1745 : {
1746 162530 : if (fsp == fsp->conn->cwd_fsp) {
1747 0 : return;
1748 : }
1749 :
1750 162530 : if (fsp->notify) {
1751 30 : size_t len = fsp_fullbasepath(fsp, NULL, 0);
1752 30 : char fullpath[len+1];
1753 :
1754 30 : fsp_fullbasepath(fsp, fullpath, sizeof(fullpath));
1755 :
1756 : /*
1757 : * Avoid /. at the end of the path name. notify can't
1758 : * deal with it.
1759 : */
1760 42 : if (len > 1 && fullpath[len-1] == '.' &&
1761 24 : fullpath[len-2] == '/') {
1762 24 : fullpath[len-2] = '\0';
1763 : }
1764 :
1765 30 : notify_remove(fsp->conn->sconn->notify_ctx, fsp, fullpath);
1766 30 : TALLOC_FREE(fsp->notify);
1767 : }
1768 :
1769 : /* Ensure this event will never fire. */
1770 162530 : TALLOC_FREE(fsp->update_write_time_event);
1771 :
1772 162530 : if (fsp->op != NULL) {
1773 16339 : fsp->op->compat = NULL;
1774 : }
1775 162530 : TALLOC_FREE(fsp->op);
1776 :
1777 162530 : if ((req != NULL) && (fsp == req->chain_fsp)) {
1778 16063 : req->chain_fsp = NULL;
1779 : }
1780 :
1781 : /*
1782 : * Clear all possible chained fsp
1783 : * pointers in the SMB2 request queue.
1784 : */
1785 162530 : remove_smb2_chained_fsp(fsp);
1786 : }
1787 :
1788 146114 : void file_free(struct smb_request *req, files_struct *fsp)
1789 : {
1790 146114 : struct smbd_server_connection *sconn = fsp->conn->sconn;
1791 146114 : uint64_t fnum = fsp->fnum;
1792 :
1793 146114 : fsp_unbind_smb(req, fsp);
1794 :
1795 : /* Drop all remaining extensions. */
1796 146114 : vfs_remove_all_fsp_extensions(fsp);
1797 :
1798 146114 : fsp_free(fsp);
1799 :
1800 146114 : DBG_INFO("freed files structure %"PRIu64" (%zu used)\n",
1801 : fnum,
1802 : sconn->num_files);
1803 146114 : }
1804 :
1805 : /****************************************************************************
1806 : Get an fsp from a packet given a 16 bit fnum.
1807 : ****************************************************************************/
1808 :
1809 0 : files_struct *file_fsp(struct smb_request *req, uint16_t fid)
1810 : {
1811 : struct smbXsrv_open *op;
1812 : NTSTATUS status;
1813 0 : NTTIME now = 0;
1814 : files_struct *fsp;
1815 :
1816 0 : if (req == NULL) {
1817 : /*
1818 : * We should never get here. req==NULL could in theory
1819 : * only happen from internal opens with a non-zero
1820 : * root_dir_fid. Internal opens just don't do that, at
1821 : * least they are not supposed to do so. And if they
1822 : * start to do so, they better fake up a smb_request
1823 : * from which we get the right smbd_server_conn. While
1824 : * this should never happen, let's return NULL here.
1825 : */
1826 0 : return NULL;
1827 : }
1828 :
1829 0 : if (req->chain_fsp != NULL) {
1830 0 : if (req->chain_fsp->fsp_flags.closing) {
1831 0 : return NULL;
1832 : }
1833 0 : return req->chain_fsp;
1834 : }
1835 :
1836 0 : if (req->xconn == NULL) {
1837 0 : return NULL;
1838 : }
1839 :
1840 0 : now = timeval_to_nttime(&req->request_time);
1841 :
1842 0 : status = smb1srv_open_lookup(req->xconn,
1843 : fid, now, &op);
1844 0 : if (!NT_STATUS_IS_OK(status)) {
1845 0 : return NULL;
1846 : }
1847 :
1848 0 : fsp = op->compat;
1849 0 : if (fsp == NULL) {
1850 0 : return NULL;
1851 : }
1852 :
1853 0 : if (fsp->fsp_flags.closing) {
1854 0 : return NULL;
1855 : }
1856 :
1857 0 : req->chain_fsp = fsp;
1858 0 : return fsp;
1859 : }
1860 :
1861 114138 : struct files_struct *file_fsp_get(struct smbd_smb2_request *smb2req,
1862 : uint64_t persistent_id,
1863 : uint64_t volatile_id)
1864 : {
1865 : struct smbXsrv_open *op;
1866 : NTSTATUS status;
1867 114138 : NTTIME now = 0;
1868 : struct files_struct *fsp;
1869 :
1870 114138 : now = timeval_to_nttime(&smb2req->request_time);
1871 :
1872 114138 : status = smb2srv_open_lookup(smb2req->xconn,
1873 : persistent_id, volatile_id,
1874 : now, &op);
1875 114138 : if (!NT_STATUS_IS_OK(status)) {
1876 1661 : return NULL;
1877 : }
1878 :
1879 112477 : fsp = op->compat;
1880 112477 : if (fsp == NULL) {
1881 0 : return NULL;
1882 : }
1883 :
1884 112477 : if (smb2req->tcon == NULL) {
1885 0 : return NULL;
1886 : }
1887 :
1888 112477 : if (smb2req->tcon->compat != fsp->conn) {
1889 0 : return NULL;
1890 : }
1891 :
1892 112477 : if (smb2req->session == NULL) {
1893 0 : return NULL;
1894 : }
1895 :
1896 112477 : if (smb2req->session->global->session_wire_id != fsp->vuid) {
1897 0 : return NULL;
1898 : }
1899 :
1900 112477 : if (fsp->fsp_flags.closing) {
1901 0 : return NULL;
1902 : }
1903 :
1904 112477 : return fsp;
1905 : }
1906 :
1907 226611 : struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
1908 : uint64_t persistent_id,
1909 : uint64_t volatile_id)
1910 : {
1911 : struct files_struct *fsp;
1912 :
1913 226611 : if (smb2req->compat_chain_fsp != NULL) {
1914 112473 : if (smb2req->compat_chain_fsp->fsp_flags.closing) {
1915 0 : return NULL;
1916 : }
1917 112473 : return smb2req->compat_chain_fsp;
1918 : }
1919 :
1920 114138 : fsp = file_fsp_get(smb2req, persistent_id, volatile_id);
1921 114138 : if (fsp == NULL) {
1922 1661 : return NULL;
1923 : }
1924 :
1925 112477 : smb2req->compat_chain_fsp = fsp;
1926 112477 : return fsp;
1927 : }
1928 :
1929 : /****************************************************************************
1930 : Duplicate the file handle part for a DOS or FCB open.
1931 : ****************************************************************************/
1932 :
1933 0 : NTSTATUS dup_file_fsp(
1934 : files_struct *from,
1935 : uint32_t access_mask,
1936 : files_struct *to)
1937 : {
1938 : size_t new_refcount;
1939 :
1940 : /* this can never happen for print files */
1941 0 : SMB_ASSERT(from->print_file == NULL);
1942 :
1943 0 : TALLOC_FREE(to->fh);
1944 :
1945 0 : to->fh = from->fh;
1946 0 : new_refcount = fh_get_refcount(to->fh) + 1;
1947 0 : fh_set_refcount(to->fh, new_refcount);
1948 :
1949 0 : to->file_id = from->file_id;
1950 0 : to->initial_allocation_size = from->initial_allocation_size;
1951 0 : to->file_pid = from->file_pid;
1952 0 : to->vuid = from->vuid;
1953 0 : to->open_time = from->open_time;
1954 0 : to->access_mask = access_mask;
1955 0 : to->oplock_type = from->oplock_type;
1956 0 : to->fsp_flags.can_lock = from->fsp_flags.can_lock;
1957 0 : to->fsp_flags.can_read = ((access_mask & FILE_READ_DATA) != 0);
1958 0 : to->fsp_flags.can_write =
1959 0 : CAN_WRITE(from->conn) &&
1960 0 : ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
1961 0 : to->fsp_flags.modified = from->fsp_flags.modified;
1962 0 : to->fsp_flags.is_directory = from->fsp_flags.is_directory;
1963 0 : to->fsp_flags.aio_write_behind = from->fsp_flags.aio_write_behind;
1964 0 : to->fsp_flags.is_fsa = from->fsp_flags.is_fsa;
1965 0 : to->fsp_flags.is_pathref = from->fsp_flags.is_pathref;
1966 0 : to->fsp_flags.have_proc_fds = from->fsp_flags.have_proc_fds;
1967 0 : to->fsp_flags.is_dirfsp = from->fsp_flags.is_dirfsp;
1968 :
1969 0 : return fsp_set_smb_fname(to, from->fsp_name);
1970 : }
1971 :
1972 : /**
1973 : * Return a jenkins hash of a pathname on a connection.
1974 : */
1975 :
1976 129256 : NTSTATUS file_name_hash(connection_struct *conn,
1977 : const char *name, uint32_t *p_name_hash)
1978 : {
1979 : char tmpbuf[PATH_MAX];
1980 : char *fullpath, *to_free;
1981 : ssize_t len;
1982 : TDB_DATA key;
1983 :
1984 : /* Set the hash of the full pathname. */
1985 :
1986 129256 : if (name[0] == '/') {
1987 35617 : strlcpy(tmpbuf, name, sizeof(tmpbuf));
1988 35617 : fullpath = tmpbuf;
1989 35617 : len = strlen(fullpath);
1990 35617 : to_free = NULL;
1991 : } else {
1992 93639 : len = full_path_tos(conn->connectpath,
1993 : name,
1994 : tmpbuf,
1995 : sizeof(tmpbuf),
1996 : &fullpath,
1997 : &to_free);
1998 : }
1999 129256 : if (len == -1) {
2000 0 : return NT_STATUS_NO_MEMORY;
2001 : }
2002 129256 : key = (TDB_DATA) { .dptr = (uint8_t *)fullpath, .dsize = len+1 };
2003 129256 : *p_name_hash = tdb_jenkins_hash(&key);
2004 :
2005 129256 : DEBUG(10,("file_name_hash: %s hash 0x%x\n",
2006 : fullpath,
2007 : (unsigned int)*p_name_hash ));
2008 :
2009 129256 : TALLOC_FREE(to_free);
2010 129256 : return NT_STATUS_OK;
2011 : }
2012 :
2013 129219 : static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
2014 : struct smb_filename **_smb_fname)
2015 : {
2016 129219 : struct smb_filename *smb_fname_new = talloc_move(fsp, _smb_fname);
2017 129219 : const char *name_str = NULL;
2018 129219 : uint32_t name_hash = 0;
2019 : NTSTATUS status;
2020 :
2021 129219 : name_str = smb_fname_str_dbg(smb_fname_new);
2022 129219 : if (name_str == NULL) {
2023 0 : return NT_STATUS_NO_MEMORY;
2024 : }
2025 :
2026 129219 : status = file_name_hash(fsp->conn,
2027 : name_str,
2028 : &name_hash);
2029 129219 : if (!NT_STATUS_IS_OK(status)) {
2030 0 : return status;
2031 : }
2032 :
2033 129219 : status = fsp_smb_fname_link(fsp,
2034 : &smb_fname_new->fsp_link,
2035 : &smb_fname_new->fsp);
2036 129219 : if (!NT_STATUS_IS_OK(status)) {
2037 0 : return status;
2038 : }
2039 :
2040 129219 : fsp->name_hash = name_hash;
2041 129219 : fsp->fsp_name = smb_fname_new;
2042 129219 : *_smb_fname = NULL;
2043 129219 : return NT_STATUS_OK;
2044 : }
2045 :
2046 : /**
2047 : * The only way that the fsp->fsp_name field should ever be set.
2048 : */
2049 16019 : NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
2050 : const struct smb_filename *smb_fname_in)
2051 : {
2052 16019 : struct smb_filename *smb_fname_old = fsp->fsp_name;
2053 16019 : struct smb_filename *smb_fname_new = NULL;
2054 : NTSTATUS status;
2055 :
2056 16019 : smb_fname_new = cp_smb_filename(fsp, smb_fname_in);
2057 16019 : if (smb_fname_new == NULL) {
2058 0 : return NT_STATUS_NO_MEMORY;
2059 : }
2060 :
2061 16019 : status = fsp_attach_smb_fname(fsp, &smb_fname_new);
2062 16019 : if (!NT_STATUS_IS_OK(status)) {
2063 0 : TALLOC_FREE(smb_fname_new);
2064 0 : return status;
2065 : }
2066 :
2067 16019 : if (smb_fname_old != NULL) {
2068 9497 : smb_fname_fsp_unlink(smb_fname_old);
2069 9497 : TALLOC_FREE(smb_fname_old);
2070 : }
2071 :
2072 16019 : return NT_STATUS_OK;
2073 : }
2074 :
2075 120 : size_t fsp_fullbasepath(struct files_struct *fsp, char *buf, size_t buflen)
2076 : {
2077 120 : int len = 0;
2078 120 : char tmp_buf[1] = {'\0'};
2079 :
2080 : /*
2081 : * Don't pass NULL buffer to snprintf (to satisfy static checker)
2082 : * Some callers will call this function with NULL for buf and
2083 : * 0 for buflen in order to get length of fullbasepath (without
2084 : * needing to allocate or write to buf)
2085 : */
2086 120 : if (buf == NULL) {
2087 60 : buf = tmp_buf;
2088 60 : SMB_ASSERT(buflen==0);
2089 : }
2090 :
2091 120 : len = snprintf(buf, buflen, "%s/%s", fsp->conn->connectpath,
2092 120 : fsp->fsp_name->base_name);
2093 120 : SMB_ASSERT(len>0);
2094 :
2095 120 : return len;
2096 : }
2097 :
2098 126652 : void fsp_set_base_fsp(struct files_struct *fsp, struct files_struct *base_fsp)
2099 : {
2100 126652 : SMB_ASSERT(fsp->stream_fsp == NULL);
2101 126652 : if (base_fsp != NULL) {
2102 136 : SMB_ASSERT(base_fsp->base_fsp == NULL);
2103 136 : SMB_ASSERT(base_fsp->stream_fsp == NULL);
2104 : }
2105 :
2106 126652 : if (fsp->base_fsp != NULL) {
2107 72 : SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
2108 72 : fsp->base_fsp->stream_fsp = NULL;
2109 : }
2110 :
2111 126652 : fsp->base_fsp = base_fsp;
2112 126652 : if (fsp->base_fsp != NULL) {
2113 136 : fsp->base_fsp->stream_fsp = fsp;
2114 : }
2115 126652 : }
2116 :
2117 495310 : bool fsp_is_alternate_stream(const struct files_struct *fsp)
2118 : {
2119 495310 : return (fsp->base_fsp != NULL);
2120 : }
2121 :
2122 59568 : struct files_struct *metadata_fsp(struct files_struct *fsp)
2123 : {
2124 59568 : if (fsp_is_alternate_stream(fsp)) {
2125 270 : return fsp->base_fsp;
2126 : }
2127 59298 : return fsp;
2128 : }
|