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 "libcli/security/security.h"
24 : #include "util_tdb.h"
25 : #include "lib/util/bitmap.h"
26 :
27 : #define FILE_HANDLE_OFFSET 0x1000
28 :
29 : static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
30 : struct smb_filename **_smb_fname);
31 :
32 : /**
33 : * create new fsp to be used for file_new or a durable handle reconnect
34 : */
35 10560528 : NTSTATUS fsp_new(struct connection_struct *conn, TALLOC_CTX *mem_ctx,
36 : files_struct **result)
37 : {
38 10560528 : NTSTATUS status = NT_STATUS_NO_MEMORY;
39 10560528 : files_struct *fsp = NULL;
40 10560528 : struct smbd_server_connection *sconn = conn->sconn;
41 :
42 10560528 : fsp = talloc_zero(mem_ctx, struct files_struct);
43 10560528 : if (fsp == NULL) {
44 0 : goto fail;
45 : }
46 :
47 : /*
48 : * This can't be a child of fsp because the file_handle can be ref'd
49 : * when doing a dos/fcb open, which will then share the file_handle
50 : * across multiple fsps.
51 : */
52 10560528 : fsp->fh = fd_handle_create(mem_ctx);
53 10560528 : if (fsp->fh == NULL) {
54 0 : goto fail;
55 : }
56 :
57 10560528 : fsp->fsp_flags.use_ofd_locks = !lp_smbd_force_process_locks(SNUM(conn));
58 : #ifndef HAVE_OFD_LOCKS
59 : fsp->fsp_flags.use_ofd_locks = false;
60 : #endif
61 :
62 10560528 : fh_set_refcount(fsp->fh, 1);
63 10560528 : fsp_set_fd(fsp, -1);
64 :
65 10560528 : fsp->fnum = FNUM_FIELD_INVALID;
66 10560528 : fsp->conn = conn;
67 10560528 : fsp->close_write_time = make_omit_timespec();
68 :
69 10560528 : DLIST_ADD(sconn->files, fsp);
70 10560528 : sconn->num_files += 1;
71 :
72 10560528 : conn->num_files_open++;
73 :
74 10560528 : DBG_INFO("allocated files structure (%u used)\n",
75 : (unsigned int)sconn->num_files);
76 :
77 10560528 : *result = fsp;
78 10560528 : return NT_STATUS_OK;
79 :
80 0 : fail:
81 0 : if (fsp != NULL) {
82 0 : TALLOC_FREE(fsp->fh);
83 : }
84 0 : TALLOC_FREE(fsp);
85 :
86 0 : return status;
87 : }
88 :
89 10560528 : void fsp_set_gen_id(files_struct *fsp)
90 : {
91 : static uint64_t gen_id = 1;
92 :
93 : /*
94 : * A billion of 64-bit increments per second gives us
95 : * more than 500 years of runtime without wrap.
96 : */
97 10560528 : gen_id++;
98 10560528 : fh_set_gen_id(fsp->fh, gen_id);
99 10560528 : }
100 :
101 : /****************************************************************************
102 : Find first available file slot.
103 : ****************************************************************************/
104 :
105 875177 : NTSTATUS fsp_bind_smb(struct files_struct *fsp, struct smb_request *req)
106 : {
107 875177 : struct smbXsrv_open *op = NULL;
108 : NTTIME now;
109 : NTSTATUS status;
110 :
111 875177 : if (req == NULL) {
112 320134 : DBG_DEBUG("INTERNAL_OPEN_ONLY, skipping smbXsrv_open\n");
113 320134 : return NT_STATUS_OK;
114 : }
115 :
116 555043 : now = timeval_to_nttime(&fsp->open_time);
117 :
118 555043 : status = smbXsrv_open_create(req->xconn,
119 555043 : fsp->conn->session_info,
120 : now,
121 : &op);
122 555043 : if (!NT_STATUS_IS_OK(status)) {
123 0 : return status;
124 : }
125 555043 : fsp->op = op;
126 555043 : op->compat = fsp;
127 555043 : fsp->fnum = op->local_id;
128 :
129 555043 : fsp->mid = req->mid;
130 555043 : req->chain_fsp = fsp;
131 :
132 555043 : DBG_DEBUG("fsp [%s] mid [%" PRIu64"]\n",
133 : fsp_str_dbg(fsp), fsp->mid);
134 :
135 555043 : return NT_STATUS_OK;
136 : }
137 :
138 608072 : NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
139 : files_struct **result)
140 : {
141 608072 : struct smbd_server_connection *sconn = conn->sconn;
142 : files_struct *fsp;
143 : NTSTATUS status;
144 :
145 608072 : status = fsp_new(conn, conn, &fsp);
146 608072 : if (!NT_STATUS_IS_OK(status)) {
147 0 : return status;
148 : }
149 :
150 608072 : GetTimeOfDay(&fsp->open_time);
151 :
152 608072 : status = fsp_bind_smb(fsp, req);
153 608072 : if (!NT_STATUS_IS_OK(status)) {
154 0 : file_free(NULL, fsp);
155 0 : return status;
156 : }
157 :
158 608072 : fsp_set_gen_id(fsp);
159 :
160 : /*
161 : * Create an smb_filename with "" for the base_name. There are very
162 : * few NULL checks, so make sure it's initialized with something. to
163 : * be safe until an audit can be done.
164 : */
165 608072 : fsp->fsp_name = synthetic_smb_fname(fsp,
166 : "",
167 : NULL,
168 : NULL,
169 : 0,
170 : 0);
171 608072 : if (fsp->fsp_name == NULL) {
172 0 : file_free(NULL, fsp);
173 0 : return NT_STATUS_NO_MEMORY;
174 : }
175 :
176 608072 : DBG_INFO("new file %s\n", fsp_fnum_dbg(fsp));
177 :
178 : /* A new fsp invalidates the positive and
179 : negative fsp_fi_cache as the new fsp is pushed
180 : at the start of the list and we search from
181 : a cache hit to the *end* of the list. */
182 :
183 608072 : ZERO_STRUCT(sconn->fsp_fi_cache);
184 :
185 608072 : *result = fsp;
186 608072 : return NT_STATUS_OK;
187 : }
188 :
189 312157 : NTSTATUS create_internal_fsp(connection_struct *conn,
190 : const struct smb_filename *smb_fname,
191 : struct files_struct **_fsp)
192 : {
193 312157 : struct files_struct *fsp = NULL;
194 : NTSTATUS status;
195 :
196 312157 : status = file_new(NULL, conn, &fsp);
197 312157 : if (!NT_STATUS_IS_OK(status)) {
198 0 : return status;
199 : }
200 :
201 312157 : status = fsp_set_smb_fname(fsp, smb_fname);
202 312157 : if (!NT_STATUS_IS_OK(status)) {
203 0 : file_free(NULL, fsp);
204 0 : return status;
205 : }
206 :
207 312157 : *_fsp = fsp;
208 312157 : return NT_STATUS_OK;
209 : }
210 :
211 : /*
212 : * Create an internal fsp for an *existing* directory.
213 : *
214 : * This should only be used by callers in the VFS that need to control the
215 : * opening of the directory. Otherwise use open_internal_dirfsp_at().
216 : */
217 302567 : NTSTATUS create_internal_dirfsp(connection_struct *conn,
218 : const struct smb_filename *smb_dname,
219 : struct files_struct **_fsp)
220 : {
221 302567 : struct files_struct *fsp = NULL;
222 : NTSTATUS status;
223 :
224 302567 : status = create_internal_fsp(conn, smb_dname, &fsp);
225 302567 : if (!NT_STATUS_IS_OK(status)) {
226 0 : return status;
227 : }
228 :
229 302567 : fsp->access_mask = FILE_LIST_DIRECTORY;
230 302567 : fsp->fsp_flags.is_directory = true;
231 302567 : fsp->fsp_flags.is_dirfsp = true;
232 :
233 302567 : *_fsp = fsp;
234 302567 : return NT_STATUS_OK;
235 : }
236 :
237 : /*
238 : * Open an internal fsp for an *existing* directory.
239 : */
240 300061 : NTSTATUS open_internal_dirfsp(connection_struct *conn,
241 : const struct smb_filename *smb_dname,
242 : int open_flags,
243 : struct files_struct **_fsp)
244 : {
245 300061 : struct files_struct *fsp = NULL;
246 : NTSTATUS status;
247 : int ret;
248 :
249 300061 : status = create_internal_dirfsp(conn, smb_dname, &fsp);
250 300061 : if (!NT_STATUS_IS_OK(status)) {
251 0 : return status;
252 : }
253 :
254 : #ifdef O_DIRECTORY
255 300061 : open_flags |= O_DIRECTORY;
256 : #endif
257 300061 : status = fd_openat(conn->cwd_fsp, fsp->fsp_name, fsp, open_flags, 0);
258 300061 : if (!NT_STATUS_IS_OK(status)) {
259 411 : DBG_INFO("Could not open fd for %s (%s)\n",
260 : smb_fname_str_dbg(smb_dname),
261 : nt_errstr(status));
262 411 : file_free(NULL, fsp);
263 411 : return status;
264 : }
265 :
266 299650 : ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
267 299650 : if (ret != 0) {
268 0 : return map_nt_error_from_unix(errno);
269 : }
270 :
271 299650 : if (!S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
272 0 : DBG_ERR("%s is not a directory!\n",
273 : smb_fname_str_dbg(smb_dname));
274 0 : file_free(NULL, fsp);
275 0 : return NT_STATUS_NOT_A_DIRECTORY;
276 : }
277 :
278 299650 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
279 :
280 299650 : *_fsp = fsp;
281 299650 : return NT_STATUS_OK;
282 : }
283 :
284 : /*
285 : * The "link" in the name doesn't imply link in the filesystem
286 : * sense. It's a object that "links" together an fsp and an smb_fname
287 : * and the link allocated as talloc child of an fsp.
288 : *
289 : * The link is created for fsps that open_smbfname_fsp() returns in
290 : * smb_fname->fsp. When this fsp is freed by fsp_free() by some caller
291 : * somewhere, the destructor fsp_smb_fname_link_destructor() on the link object
292 : * will use the link to reset the reference in smb_fname->fsp that is about to
293 : * go away.
294 : *
295 : * This prevents smb_fname_internal_fsp_destructor() from seeing dangling fsp
296 : * pointers.
297 : */
298 :
299 : struct fsp_smb_fname_link {
300 : struct fsp_smb_fname_link **smb_fname_link;
301 : struct files_struct **smb_fname_fsp;
302 : };
303 :
304 10561307 : static int fsp_smb_fname_link_destructor(struct fsp_smb_fname_link *link)
305 : {
306 10561307 : if (link->smb_fname_link == NULL) {
307 0 : return 0;
308 : }
309 :
310 10561307 : *link->smb_fname_link = NULL;
311 10561307 : *link->smb_fname_fsp = NULL;
312 10561307 : return 0;
313 : }
314 :
315 21160080 : static NTSTATUS fsp_smb_fname_link(struct files_struct *fsp,
316 : struct fsp_smb_fname_link **smb_fname_link,
317 : struct files_struct **smb_fname_fsp)
318 : {
319 21160080 : struct fsp_smb_fname_link *link = NULL;
320 :
321 21160080 : SMB_ASSERT(*smb_fname_link == NULL);
322 21160080 : SMB_ASSERT(*smb_fname_fsp == NULL);
323 :
324 21160080 : link = talloc_zero(fsp, struct fsp_smb_fname_link);
325 21160080 : if (link == NULL) {
326 0 : return NT_STATUS_NO_MEMORY;
327 : }
328 :
329 21160080 : link->smb_fname_link = smb_fname_link;
330 21160080 : link->smb_fname_fsp = smb_fname_fsp;
331 21160080 : *smb_fname_link = link;
332 21160080 : *smb_fname_fsp = fsp;
333 :
334 21160080 : talloc_set_destructor(link, fsp_smb_fname_link_destructor);
335 21160080 : return NT_STATUS_OK;
336 : }
337 :
338 : /*
339 : * Free a link, carefully avoiding to trigger the link destructor
340 : */
341 11207612 : static void destroy_fsp_smb_fname_link(struct fsp_smb_fname_link **_link)
342 : {
343 11207612 : struct fsp_smb_fname_link *link = *_link;
344 :
345 11207612 : if (link == NULL) {
346 607132 : return;
347 : }
348 10598757 : talloc_set_destructor(link, NULL);
349 10598757 : TALLOC_FREE(link);
350 10598757 : *_link = NULL;
351 : }
352 :
353 : /*
354 : * Talloc destructor set on an smb_fname set by openat_pathref_fsp() used to
355 : * close the embedded smb_fname->fsp.
356 : */
357 9619758 : static int smb_fname_fsp_destructor(struct smb_filename *smb_fname)
358 : {
359 9619758 : struct files_struct *fsp = smb_fname->fsp;
360 : NTSTATUS status;
361 9619758 : int saved_errno = errno;
362 :
363 9619758 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
364 :
365 9619758 : if (fsp == NULL) {
366 805 : errno = saved_errno;
367 805 : return 0;
368 : }
369 :
370 9618953 : if (fsp->base_fsp != NULL) {
371 1674 : struct files_struct *tmp_base_fsp = fsp->base_fsp;
372 :
373 1674 : fsp_set_base_fsp(fsp, NULL);
374 :
375 1674 : status = fd_close(tmp_base_fsp);
376 1674 : SMB_ASSERT(NT_STATUS_IS_OK(status));
377 1674 : file_free(NULL, tmp_base_fsp);
378 : }
379 :
380 9618953 : status = fd_close(fsp);
381 9618953 : SMB_ASSERT(NT_STATUS_IS_OK(status));
382 9618953 : file_free(NULL, fsp);
383 9618953 : smb_fname->fsp = NULL;
384 :
385 9618953 : errno = saved_errno;
386 9618953 : return 0;
387 : }
388 :
389 : /*
390 : * For proper streams support, we have to open the base_fsp for pathref
391 : * fsp's as well.
392 : */
393 4724 : static NTSTATUS open_pathref_base_fsp(const struct files_struct *dirfsp,
394 : struct files_struct *fsp)
395 : {
396 4724 : struct smb_filename *smb_fname_base = NULL;
397 : NTSTATUS status;
398 : int ret;
399 :
400 13362 : smb_fname_base = synthetic_smb_fname(talloc_tos(),
401 4724 : fsp->fsp_name->base_name,
402 : NULL,
403 : NULL,
404 4718 : fsp->fsp_name->twrp,
405 4724 : fsp->fsp_name->flags);
406 4724 : if (smb_fname_base == NULL) {
407 0 : return NT_STATUS_NO_MEMORY;
408 : }
409 :
410 4724 : ret = vfs_stat(fsp->conn, smb_fname_base);
411 4724 : if (ret != 0) {
412 0 : return map_nt_error_from_unix(errno);
413 : }
414 :
415 4724 : status = openat_pathref_fsp(dirfsp, smb_fname_base);
416 4724 : if (!NT_STATUS_IS_OK(status)) {
417 0 : TALLOC_FREE(smb_fname_base);
418 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
419 0 : DBG_DEBUG("Opening base file failed: %s\n",
420 : nt_errstr(status));
421 0 : return status;
422 : }
423 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
424 : }
425 :
426 4724 : fsp_set_base_fsp(fsp, smb_fname_base->fsp);
427 4724 : smb_fname_fsp_unlink(smb_fname_base);
428 4724 : TALLOC_FREE(smb_fname_base);
429 :
430 4724 : return NT_STATUS_OK;
431 : }
432 :
433 : /*
434 : * Open an internal O_PATH based fsp for smb_fname. If O_PATH is not
435 : * available, open O_RDONLY as root. Both is done in fd_open() ->
436 : * non_widelink_open(), triggered by setting fsp->fsp_flags.is_pathref to
437 : * true.
438 : */
439 9953826 : NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
440 : struct smb_filename *smb_fname)
441 : {
442 9953826 : connection_struct *conn = dirfsp->conn;
443 9953826 : struct smb_filename *full_fname = NULL;
444 9953826 : struct files_struct *fsp = NULL;
445 9953826 : int open_flags = O_RDONLY;
446 : NTSTATUS status;
447 :
448 9953826 : DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
449 :
450 9953826 : if (smb_fname->fsp != NULL) {
451 : /* We already have one for this name. */
452 418 : DBG_DEBUG("smb_fname [%s] already has a pathref fsp.\n",
453 : smb_fname_str_dbg(smb_fname));
454 418 : return NT_STATUS_OK;
455 : }
456 :
457 9953408 : if (!VALID_STAT(smb_fname->st)) {
458 340 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
459 : }
460 :
461 9953068 : if (S_ISLNK(smb_fname->st.st_ex_mode)) {
462 748 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
463 : }
464 :
465 9952320 : status = fsp_new(conn, conn, &fsp);
466 9952320 : if (!NT_STATUS_IS_OK(status)) {
467 0 : return status;
468 : }
469 :
470 9952320 : GetTimeOfDay(&fsp->open_time);
471 9952320 : fsp_set_gen_id(fsp);
472 9952320 : ZERO_STRUCT(conn->sconn->fsp_fi_cache);
473 :
474 9952320 : fsp->fsp_flags.is_pathref = true;
475 9952320 : if (S_ISDIR(smb_fname->st.st_ex_mode)) {
476 8904437 : fsp->fsp_flags.is_directory = true;
477 8904437 : open_flags |= O_DIRECTORY;
478 : }
479 :
480 9952320 : full_fname = full_path_from_dirfsp_atname(fsp,
481 : dirfsp,
482 : smb_fname);
483 9952320 : if (full_fname == NULL) {
484 0 : status = NT_STATUS_NO_MEMORY;
485 0 : goto fail;
486 : }
487 :
488 9952320 : if (is_ntfs_default_stream_smb_fname(full_fname)) {
489 92 : full_fname->stream_name = NULL;
490 : }
491 :
492 9952320 : status = fsp_attach_smb_fname(fsp, &full_fname);
493 9952320 : if (!NT_STATUS_IS_OK(status)) {
494 0 : goto fail;
495 : }
496 :
497 9952320 : if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
498 9592106 : && is_ntfs_stream_smb_fname(fsp->fsp_name))
499 : {
500 4724 : status = open_pathref_base_fsp(dirfsp, fsp);
501 4724 : if (!NT_STATUS_IS_OK(status)) {
502 0 : goto fail;
503 : }
504 : }
505 :
506 9952320 : if (S_ISFIFO(smb_fname->st.st_ex_mode)) {
507 2 : open_flags |= O_NONBLOCK;
508 : }
509 :
510 9952320 : status = fd_openat(dirfsp, smb_fname, fsp, open_flags, 0);
511 9952320 : if (!NT_STATUS_IS_OK(status)) {
512 115088 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) ||
513 115088 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
514 59753 : NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK))
515 : {
516 : /*
517 : * streams_xattr return NT_STATUS_NOT_FOUND for
518 : * opens of not yet exisiting streams.
519 : *
520 : * ELOOP maps to NT_STATUS_OBJECT_PATH_NOT_FOUND
521 : * and this will result from a open request from
522 : * a POSIX client on a symlink.
523 : *
524 : * NT_STATUS_OBJECT_NAME_NOT_FOUND is the simple
525 : * ENOENT case.
526 : *
527 : * NT_STATUS_STOPPED_ON_SYMLINK is returned when trying
528 : * to open a symlink, our callers are not interested in
529 : * this.
530 : */
531 268 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
532 : }
533 59753 : goto fail;
534 : }
535 :
536 9892023 : if (!check_same_dev_ino(&smb_fname->st, &fsp->fsp_name->st)) {
537 484 : DBG_DEBUG("file [%s] - dev/ino mismatch. "
538 : "Old (dev=%ju, ino=%ju). "
539 : "New (dev=%ju, ino=%ju).\n",
540 : smb_fname_str_dbg(smb_fname),
541 : (uintmax_t)smb_fname->st.st_ex_dev,
542 : (uintmax_t)smb_fname->st.st_ex_ino,
543 : (uintmax_t)fsp->fsp_name->st.st_ex_dev,
544 : (uintmax_t)fsp->fsp_name->st.st_ex_ino);
545 484 : status = NT_STATUS_ACCESS_DENIED;
546 484 : goto fail;
547 : }
548 :
549 : /*
550 : * fd_openat() has done an FSTAT on the handle
551 : * so update the smb_fname stat info with "truth".
552 : * from the handle.
553 : */
554 9891539 : smb_fname->st = fsp->fsp_name->st;
555 :
556 9891539 : fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
557 :
558 9891539 : status = fsp_smb_fname_link(fsp,
559 : &smb_fname->fsp_link,
560 : &smb_fname->fsp);
561 9891539 : if (!NT_STATUS_IS_OK(status)) {
562 0 : goto fail;
563 : }
564 :
565 9891539 : DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp));
566 :
567 9891539 : talloc_set_destructor(smb_fname, smb_fname_fsp_destructor);
568 9891539 : return NT_STATUS_OK;
569 :
570 60237 : fail:
571 60781 : DBG_DEBUG("Opening pathref for [%s] failed: %s\n",
572 : smb_fname_str_dbg(smb_fname),
573 : nt_errstr(status));
574 :
575 60781 : if (fsp == NULL) {
576 0 : return status;
577 : }
578 60781 : if (fsp->base_fsp != NULL) {
579 6 : struct files_struct *tmp_base_fsp = fsp->base_fsp;
580 :
581 6 : fsp_set_base_fsp(fsp, NULL);
582 :
583 6 : fd_close(tmp_base_fsp);
584 6 : file_free(NULL, tmp_base_fsp);
585 : }
586 60781 : fd_close(fsp);
587 60781 : file_free(NULL, fsp);
588 60781 : return status;
589 : }
590 :
591 1403853 : void smb_fname_fsp_unlink(struct smb_filename *smb_fname)
592 : {
593 1403853 : talloc_set_destructor(smb_fname, NULL);
594 1403853 : smb_fname->fsp = NULL;
595 1403853 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
596 1403853 : }
597 :
598 : /*
599 : * Move any existing embedded fsp refs from the src name to the
600 : * destination. It's safe to call this on src smb_fname's that have no embedded
601 : * pathref fsp.
602 : */
603 523958 : NTSTATUS move_smb_fname_fsp_link(struct smb_filename *smb_fname_dst,
604 : struct smb_filename *smb_fname_src)
605 : {
606 : NTSTATUS status;
607 :
608 : /*
609 : * The target should always not be linked yet!
610 : */
611 523958 : SMB_ASSERT(smb_fname_dst->fsp == NULL);
612 523958 : SMB_ASSERT(smb_fname_dst->fsp_link == NULL);
613 :
614 523958 : if (smb_fname_src->fsp == NULL) {
615 568 : return NT_STATUS_OK;
616 : }
617 :
618 523390 : status = fsp_smb_fname_link(smb_fname_src->fsp,
619 : &smb_fname_dst->fsp_link,
620 : &smb_fname_dst->fsp);
621 523390 : if (!NT_STATUS_IS_OK(status)) {
622 0 : return status;
623 : }
624 :
625 523390 : talloc_set_destructor(smb_fname_dst, smb_fname_fsp_destructor);
626 :
627 523390 : smb_fname_fsp_unlink(smb_fname_src);
628 :
629 523390 : return NT_STATUS_OK;
630 : }
631 :
632 : /**
633 : * Create an smb_fname and open smb_fname->fsp pathref
634 : **/
635 236543 : NTSTATUS synthetic_pathref(TALLOC_CTX *mem_ctx,
636 : struct files_struct *dirfsp,
637 : const char *base_name,
638 : const char *stream_name,
639 : const SMB_STRUCT_STAT *psbuf,
640 : NTTIME twrp,
641 : uint32_t flags,
642 : struct smb_filename **_smb_fname)
643 : {
644 236543 : struct smb_filename *smb_fname = NULL;
645 : NTSTATUS status;
646 : int ret;
647 :
648 236543 : smb_fname = synthetic_smb_fname(mem_ctx,
649 : base_name,
650 : stream_name,
651 : psbuf,
652 : twrp,
653 : flags);
654 236543 : if (smb_fname == NULL) {
655 0 : return NT_STATUS_NO_MEMORY;
656 : }
657 :
658 236543 : if (!VALID_STAT(smb_fname->st)) {
659 234987 : ret = vfs_stat(dirfsp->conn, smb_fname);
660 234987 : if (ret != 0) {
661 197290 : int err = errno;
662 197290 : int lvl = err == ENOENT ? DBGLVL_INFO : DBGLVL_ERR;
663 197290 : DBG_PREFIX(lvl, ("stat [%s] failed: %s\n",
664 : smb_fname_str_dbg(smb_fname),
665 : strerror(err)));
666 197290 : TALLOC_FREE(smb_fname);
667 197290 : return map_nt_error_from_unix(err);
668 : }
669 : }
670 :
671 39253 : status = openat_pathref_fsp(dirfsp, smb_fname);
672 39253 : if (!NT_STATUS_IS_OK(status)) {
673 154 : DBG_ERR("opening [%s] failed\n",
674 : smb_fname_str_dbg(smb_fname));
675 154 : TALLOC_FREE(smb_fname);
676 154 : return status;
677 : }
678 :
679 39099 : *_smb_fname = smb_fname;
680 39099 : return NT_STATUS_OK;
681 : }
682 :
683 184001 : static int atname_destructor(struct smb_filename *smb_fname)
684 : {
685 184001 : destroy_fsp_smb_fname_link(&smb_fname->fsp_link);
686 184001 : return 0;
687 : }
688 :
689 : /**
690 : * Turn a path into a parent pathref and atname
691 : *
692 : * This returns the parent pathref in _parent and the name relative to it. If
693 : * smb_fname was a pathref (ie smb_fname->fsp != NULL), then _atname will be a
694 : * pathref as well, ie _atname->fsp will point at the same fsp as
695 : * smb_fname->fsp.
696 : **/
697 748881 : NTSTATUS parent_pathref(TALLOC_CTX *mem_ctx,
698 : struct files_struct *dirfsp,
699 : const struct smb_filename *smb_fname,
700 : struct smb_filename **_parent,
701 : struct smb_filename **_atname)
702 : {
703 748881 : struct smb_filename *parent = NULL;
704 748881 : struct smb_filename *atname = NULL;
705 : NTSTATUS status;
706 : int ret;
707 :
708 748881 : status = SMB_VFS_PARENT_PATHNAME(dirfsp->conn,
709 : mem_ctx,
710 : smb_fname,
711 : &parent,
712 : &atname);
713 748881 : if (!NT_STATUS_IS_OK(status)) {
714 0 : return status;
715 : }
716 :
717 : /*
718 : * We know that the parent name must
719 : * exist, and the name has been canonicalized
720 : * even if this was a POSIX pathname.
721 : * Ensure that we follow symlinks for
722 : * the parent. See the torture test
723 : * POSIX-SYMLINK-PARENT for details.
724 : */
725 748881 : parent->flags &= ~SMB_FILENAME_POSIX_PATH;
726 :
727 748881 : ret = vfs_stat(dirfsp->conn, parent);
728 748881 : if (ret != 0) {
729 364 : TALLOC_FREE(parent);
730 364 : return map_nt_error_from_unix(errno);
731 : }
732 :
733 748517 : status = openat_pathref_fsp(dirfsp, parent);
734 748517 : if (!NT_STATUS_IS_OK(status)) {
735 0 : TALLOC_FREE(parent);
736 0 : return status;
737 : }
738 :
739 748517 : if (smb_fname->fsp != NULL) {
740 340317 : status = fsp_smb_fname_link(smb_fname->fsp,
741 183788 : &atname->fsp_link,
742 184001 : &atname->fsp);
743 184001 : if (!NT_STATUS_IS_OK(status)) {
744 0 : TALLOC_FREE(parent);
745 0 : return status;
746 : }
747 184001 : talloc_set_destructor(atname, atname_destructor);
748 : }
749 748517 : *_parent = parent;
750 748517 : *_atname = atname;
751 748517 : return NT_STATUS_OK;
752 : }
753 :
754 : /****************************************************************************
755 : Close all open files for a connection.
756 : ****************************************************************************/
757 :
758 42170 : void file_close_conn(connection_struct *conn)
759 : {
760 : files_struct *fsp, *next;
761 :
762 44128 : for (fsp=conn->sconn->files; fsp; fsp=next) {
763 1431 : next = fsp->next;
764 1431 : if (fsp->conn != conn) {
765 1102 : continue;
766 : }
767 329 : if (fsp->op != NULL && fsp->op->global->durable) {
768 : /*
769 : * A tree disconnect closes a durable handle
770 : */
771 4 : fsp->op->global->durable = false;
772 : }
773 329 : close_file(NULL, fsp, SHUTDOWN_CLOSE);
774 : }
775 42170 : }
776 :
777 : /****************************************************************************
778 : Initialise file structures.
779 : ****************************************************************************/
780 :
781 : static int files_max_open_fds;
782 :
783 27337 : bool file_init_global(void)
784 : {
785 27337 : int request_max = lp_max_open_files();
786 : int real_lim;
787 : int real_max;
788 :
789 27337 : if (files_max_open_fds != 0) {
790 26731 : return true;
791 : }
792 :
793 : /*
794 : * Set the max_open files to be the requested
795 : * max plus a fudgefactor to allow for the extra
796 : * fd's we need such as log files etc...
797 : */
798 76 : real_lim = set_maxfiles(request_max + MAX_OPEN_FUDGEFACTOR);
799 :
800 76 : real_max = real_lim - MAX_OPEN_FUDGEFACTOR;
801 :
802 76 : if (real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) {
803 0 : real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
804 : }
805 :
806 76 : if (real_max != request_max) {
807 0 : DEBUG(1, ("file_init_global: Information only: requested %d "
808 : "open files, %d are available.\n",
809 : request_max, real_max));
810 : }
811 :
812 76 : SMB_ASSERT(real_max > 100);
813 :
814 76 : files_max_open_fds = real_max;
815 76 : return true;
816 : }
817 :
818 27277 : bool file_init(struct smbd_server_connection *sconn)
819 : {
820 : bool ok;
821 :
822 27277 : ok = file_init_global();
823 27277 : if (!ok) {
824 0 : return false;
825 : }
826 :
827 27277 : sconn->real_max_open_files = files_max_open_fds;
828 :
829 27277 : return true;
830 : }
831 :
832 : /****************************************************************************
833 : Close files open by a specified vuid.
834 : ****************************************************************************/
835 :
836 27379 : void file_close_user(struct smbd_server_connection *sconn, uint64_t vuid)
837 : {
838 : files_struct *fsp, *next;
839 :
840 29742 : for (fsp=sconn->files; fsp; fsp=next) {
841 1841 : next=fsp->next;
842 1841 : if (fsp->vuid == vuid) {
843 1747 : close_file(NULL, fsp, SHUTDOWN_CLOSE);
844 : }
845 : }
846 27379 : }
847 :
848 : /*
849 : * Walk the files table until "fn" returns non-NULL
850 : */
851 :
852 146160 : struct files_struct *files_forall(
853 : struct smbd_server_connection *sconn,
854 : struct files_struct *(*fn)(struct files_struct *fsp,
855 : void *private_data),
856 : void *private_data)
857 : {
858 : struct files_struct *fsp, *next;
859 :
860 337018 : for (fsp = sconn->files; fsp; fsp = next) {
861 : struct files_struct *ret;
862 192578 : next = fsp->next;
863 192578 : ret = fn(fsp, private_data);
864 192578 : if (ret != NULL) {
865 1953 : return ret;
866 : }
867 : }
868 143974 : return NULL;
869 : }
870 :
871 : /****************************************************************************
872 : Find a fsp given a file descriptor.
873 : ****************************************************************************/
874 :
875 4 : files_struct *file_find_fd(struct smbd_server_connection *sconn, int fd)
876 : {
877 4 : int count=0;
878 : files_struct *fsp;
879 :
880 4 : for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
881 4 : if (fsp_get_pathref_fd(fsp) == fd) {
882 4 : if (count > 10) {
883 0 : DLIST_PROMOTE(sconn->files, fsp);
884 : }
885 4 : return fsp;
886 : }
887 : }
888 :
889 0 : return NULL;
890 : }
891 :
892 : /****************************************************************************
893 : Find a fsp given a device, inode and file_id.
894 : ****************************************************************************/
895 :
896 14725 : files_struct *file_find_dif(struct smbd_server_connection *sconn,
897 : struct file_id id, unsigned long gen_id)
898 : {
899 14725 : int count=0;
900 : files_struct *fsp;
901 :
902 14725 : if (gen_id == 0) {
903 0 : return NULL;
904 : }
905 :
906 202611 : for (fsp = sconn->files; fsp; fsp = fsp->next,count++) {
907 : /*
908 : * We can have a fsp->fh->fd == -1 here as it could be a stat
909 : * open.
910 : */
911 202611 : if (!file_id_equal(&fsp->file_id, &id)) {
912 16642 : continue;
913 : }
914 185969 : if (!fsp->fsp_flags.is_fsa) {
915 14682 : continue;
916 : }
917 171287 : if (fh_get_gen_id(fsp->fh) != gen_id) {
918 156562 : continue;
919 : }
920 14725 : if (count > 10) {
921 4646 : DLIST_PROMOTE(sconn->files, fsp);
922 : }
923 : /* Paranoia check. */
924 14725 : if ((fsp_get_pathref_fd(fsp) == -1) &&
925 0 : (fsp->oplock_type != NO_OPLOCK &&
926 0 : fsp->oplock_type != LEASE_OPLOCK))
927 : {
928 : struct file_id_buf idbuf;
929 :
930 0 : DBG_ERR("file %s file_id = "
931 : "%s, gen = %u oplock_type = %u is a "
932 : "stat open with oplock type !\n",
933 : fsp_str_dbg(fsp),
934 : file_id_str_buf(fsp->file_id, &idbuf),
935 : (unsigned int)fh_get_gen_id(fsp->fh),
936 : (unsigned int)fsp->oplock_type);
937 0 : smb_panic("file_find_dif");
938 : }
939 14666 : return fsp;
940 : }
941 :
942 0 : return NULL;
943 : }
944 :
945 : /****************************************************************************
946 : Find the first fsp given a device and inode.
947 : We use a singleton cache here to speed up searching from getfilepathinfo
948 : calls.
949 : ****************************************************************************/
950 :
951 11564 : files_struct *file_find_di_first(struct smbd_server_connection *sconn,
952 : struct file_id id,
953 : bool need_fsa)
954 : {
955 : files_struct *fsp;
956 :
957 11564 : if (file_id_equal(&sconn->fsp_fi_cache.id, &id)) {
958 : /* Positive or negative cache hit. */
959 0 : return sconn->fsp_fi_cache.fsp;
960 : }
961 :
962 11564 : sconn->fsp_fi_cache.id = id;
963 :
964 25152 : for (fsp=sconn->files;fsp;fsp=fsp->next) {
965 16614 : if (need_fsa && !fsp->fsp_flags.is_fsa) {
966 8885 : continue;
967 : }
968 7729 : if (file_id_equal(&fsp->file_id, &id)) {
969 : /* Setup positive cache. */
970 3026 : sconn->fsp_fi_cache.fsp = fsp;
971 3026 : return fsp;
972 : }
973 : }
974 :
975 : /* Setup negative cache. */
976 8538 : sconn->fsp_fi_cache.fsp = NULL;
977 8538 : return NULL;
978 : }
979 :
980 : /****************************************************************************
981 : Find the next fsp having the same device and inode.
982 : ****************************************************************************/
983 :
984 1290 : files_struct *file_find_di_next(files_struct *start_fsp,
985 : bool need_fsa)
986 : {
987 : files_struct *fsp;
988 :
989 1484 : for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
990 347 : if (need_fsa && !fsp->fsp_flags.is_fsa) {
991 0 : continue;
992 : }
993 347 : if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
994 148 : return fsp;
995 : }
996 : }
997 :
998 1118 : return NULL;
999 : }
1000 :
1001 4 : struct files_struct *file_find_one_fsp_from_lease_key(
1002 : struct smbd_server_connection *sconn,
1003 : const struct smb2_lease_key *lease_key)
1004 : {
1005 : struct files_struct *fsp;
1006 :
1007 4 : for (fsp = sconn->files; fsp; fsp=fsp->next) {
1008 8 : if ((fsp->lease != NULL) &&
1009 4 : (fsp->lease->lease.lease_key.data[0] ==
1010 8 : lease_key->data[0]) &&
1011 4 : (fsp->lease->lease.lease_key.data[1] ==
1012 4 : lease_key->data[1])) {
1013 4 : return fsp;
1014 : }
1015 : }
1016 0 : return NULL;
1017 : }
1018 :
1019 : /****************************************************************************
1020 : Find any fsp open with a pathname below that of an already open path.
1021 : ****************************************************************************/
1022 :
1023 79 : bool file_find_subpath(files_struct *dir_fsp)
1024 : {
1025 : files_struct *fsp;
1026 : size_t dlen;
1027 79 : char *d_fullname = NULL;
1028 :
1029 121 : d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
1030 79 : dir_fsp->conn->connectpath,
1031 79 : dir_fsp->fsp_name->base_name);
1032 :
1033 79 : if (!d_fullname) {
1034 0 : return false;
1035 : }
1036 :
1037 79 : dlen = strlen(d_fullname);
1038 :
1039 288 : for (fsp=dir_fsp->conn->sconn->files; fsp; fsp=fsp->next) {
1040 : char *d1_fullname;
1041 :
1042 214 : if (fsp == dir_fsp) {
1043 77 : continue;
1044 : }
1045 :
1046 208 : d1_fullname = talloc_asprintf(talloc_tos(),
1047 : "%s/%s",
1048 137 : fsp->conn->connectpath,
1049 137 : fsp->fsp_name->base_name);
1050 :
1051 : /*
1052 : * If the open file has a path that is a longer
1053 : * component, then it's a subpath.
1054 : */
1055 148 : if (strnequal(d_fullname, d1_fullname, dlen) &&
1056 17 : (d1_fullname[dlen] == '/')) {
1057 5 : TALLOC_FREE(d1_fullname);
1058 5 : TALLOC_FREE(d_fullname);
1059 5 : return true;
1060 : }
1061 132 : TALLOC_FREE(d1_fullname);
1062 : }
1063 :
1064 74 : TALLOC_FREE(d_fullname);
1065 74 : return false;
1066 : }
1067 :
1068 : /****************************************************************************
1069 : Free up a fsp.
1070 : ****************************************************************************/
1071 :
1072 10560512 : static void fsp_free(files_struct *fsp)
1073 : {
1074 10560512 : struct smbd_server_connection *sconn = fsp->conn->sconn;
1075 :
1076 10560512 : if (fsp == sconn->fsp_fi_cache.fsp) {
1077 1130 : ZERO_STRUCT(sconn->fsp_fi_cache);
1078 : }
1079 :
1080 10560512 : DLIST_REMOVE(sconn->files, fsp);
1081 10560512 : SMB_ASSERT(sconn->num_files > 0);
1082 10560512 : sconn->num_files--;
1083 :
1084 10560512 : TALLOC_FREE(fsp->fake_file_handle);
1085 :
1086 10560512 : if (fh_get_refcount(fsp->fh) == 1) {
1087 10560399 : TALLOC_FREE(fsp->fh);
1088 : } else {
1089 113 : size_t new_refcount = fh_get_refcount(fsp->fh) - 1;
1090 113 : fh_set_refcount(fsp->fh, new_refcount);
1091 : }
1092 :
1093 10560512 : if (fsp->lease != NULL) {
1094 1006 : if (fsp->lease->ref_count == 1) {
1095 794 : TALLOC_FREE(fsp->lease);
1096 : } else {
1097 212 : fsp->lease->ref_count--;
1098 : }
1099 : }
1100 :
1101 10560512 : fsp->conn->num_files_open--;
1102 :
1103 19206906 : if (fsp->fsp_name != NULL &&
1104 10560504 : fsp->fsp_name->fsp_link != NULL)
1105 : {
1106 : /*
1107 : * Free fsp_link of fsp->fsp_name. To do this in the correct
1108 : * talloc destructor order we have to do it here. The
1109 : * talloc_free() of the link should set the fsp pointer to NULL.
1110 : */
1111 10560476 : TALLOC_FREE(fsp->fsp_name->fsp_link);
1112 10560476 : SMB_ASSERT(fsp->fsp_name->fsp == NULL);
1113 : }
1114 :
1115 : /* this is paranoia, just in case someone tries to reuse the
1116 : information */
1117 10560512 : ZERO_STRUCTP(fsp);
1118 :
1119 : /* fsp->fsp_name is a talloc child and is free'd automatically. */
1120 10560512 : TALLOC_FREE(fsp);
1121 10560512 : }
1122 :
1123 10560512 : void file_free(struct smb_request *req, files_struct *fsp)
1124 : {
1125 10560512 : struct smbd_server_connection *sconn = fsp->conn->sconn;
1126 10560512 : uint64_t fnum = fsp->fnum;
1127 :
1128 10560512 : if (fsp == fsp->conn->cwd_fsp) {
1129 0 : return;
1130 : }
1131 :
1132 10560512 : if (fsp->notify) {
1133 1850 : size_t len = fsp_fullbasepath(fsp, NULL, 0);
1134 1850 : char fullpath[len+1];
1135 :
1136 1850 : fsp_fullbasepath(fsp, fullpath, sizeof(fullpath));
1137 :
1138 : /*
1139 : * Avoid /. at the end of the path name. notify can't
1140 : * deal with it.
1141 : */
1142 1902 : if (len > 1 && fullpath[len-1] == '.' &&
1143 80 : fullpath[len-2] == '/') {
1144 80 : fullpath[len-2] = '\0';
1145 : }
1146 :
1147 1850 : notify_remove(fsp->conn->sconn->notify_ctx, fsp, fullpath);
1148 1850 : TALLOC_FREE(fsp->notify);
1149 : }
1150 :
1151 : /* Ensure this event will never fire. */
1152 10560512 : TALLOC_FREE(fsp->update_write_time_event);
1153 :
1154 10560512 : if (fsp->op != NULL) {
1155 555155 : fsp->op->compat = NULL;
1156 : }
1157 10560512 : TALLOC_FREE(fsp->op);
1158 :
1159 10560512 : if ((req != NULL) && (fsp == req->chain_fsp)) {
1160 545723 : req->chain_fsp = NULL;
1161 : }
1162 :
1163 : /*
1164 : * Clear all possible chained fsp
1165 : * pointers in the SMB2 request queue.
1166 : */
1167 10560512 : remove_smb2_chained_fsp(fsp);
1168 :
1169 : /* Drop all remaining extensions. */
1170 10560512 : vfs_remove_all_fsp_extensions(fsp);
1171 :
1172 10560512 : fsp_free(fsp);
1173 :
1174 10560512 : DEBUG(5,("freed files structure %llu (%u used)\n",
1175 : (unsigned long long)fnum, (unsigned int)sconn->num_files));
1176 : }
1177 :
1178 : /****************************************************************************
1179 : Get an fsp from a packet given a 16 bit fnum.
1180 : ****************************************************************************/
1181 :
1182 210620 : files_struct *file_fsp(struct smb_request *req, uint16_t fid)
1183 : {
1184 : struct smbXsrv_open *op;
1185 : NTSTATUS status;
1186 210620 : NTTIME now = 0;
1187 : files_struct *fsp;
1188 :
1189 210620 : if (req == NULL) {
1190 : /*
1191 : * We should never get here. req==NULL could in theory
1192 : * only happen from internal opens with a non-zero
1193 : * root_dir_fid. Internal opens just don't do that, at
1194 : * least they are not supposed to do so. And if they
1195 : * start to do so, they better fake up a smb_request
1196 : * from which we get the right smbd_server_conn. While
1197 : * this should never happen, let's return NULL here.
1198 : */
1199 0 : return NULL;
1200 : }
1201 :
1202 210620 : if (req->chain_fsp != NULL) {
1203 96 : if (req->chain_fsp->fsp_flags.closing) {
1204 0 : return NULL;
1205 : }
1206 96 : return req->chain_fsp;
1207 : }
1208 :
1209 210524 : if (req->xconn == NULL) {
1210 0 : return NULL;
1211 : }
1212 :
1213 210524 : now = timeval_to_nttime(&req->request_time);
1214 :
1215 210524 : status = smb1srv_open_lookup(req->xconn,
1216 : fid, now, &op);
1217 210524 : if (!NT_STATUS_IS_OK(status)) {
1218 2686 : return NULL;
1219 : }
1220 :
1221 207779 : fsp = op->compat;
1222 207779 : if (fsp == NULL) {
1223 0 : return NULL;
1224 : }
1225 :
1226 207779 : if (fsp->fsp_flags.closing) {
1227 0 : return NULL;
1228 : }
1229 :
1230 207779 : req->chain_fsp = fsp;
1231 207779 : return fsp;
1232 : }
1233 :
1234 794659 : struct files_struct *file_fsp_get(struct smbd_smb2_request *smb2req,
1235 : uint64_t persistent_id,
1236 : uint64_t volatile_id)
1237 : {
1238 : struct smbXsrv_open *op;
1239 : NTSTATUS status;
1240 794659 : NTTIME now = 0;
1241 : struct files_struct *fsp;
1242 :
1243 794659 : now = timeval_to_nttime(&smb2req->request_time);
1244 :
1245 794659 : status = smb2srv_open_lookup(smb2req->xconn,
1246 : persistent_id, volatile_id,
1247 : now, &op);
1248 794659 : if (!NT_STATUS_IS_OK(status)) {
1249 12164 : return NULL;
1250 : }
1251 :
1252 782495 : fsp = op->compat;
1253 782495 : if (fsp == NULL) {
1254 0 : return NULL;
1255 : }
1256 :
1257 782495 : if (smb2req->tcon == NULL) {
1258 0 : return NULL;
1259 : }
1260 :
1261 782495 : if (smb2req->tcon->compat != fsp->conn) {
1262 4 : return NULL;
1263 : }
1264 :
1265 782491 : if (smb2req->session == NULL) {
1266 0 : return NULL;
1267 : }
1268 :
1269 782491 : if (smb2req->session->global->session_wire_id != fsp->vuid) {
1270 0 : return NULL;
1271 : }
1272 :
1273 782491 : if (fsp->fsp_flags.closing) {
1274 0 : return NULL;
1275 : }
1276 :
1277 782491 : return fsp;
1278 : }
1279 :
1280 1577016 : struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
1281 : uint64_t persistent_id,
1282 : uint64_t volatile_id)
1283 : {
1284 : struct files_struct *fsp;
1285 :
1286 1577016 : if (smb2req->compat_chain_fsp != NULL) {
1287 782357 : if (smb2req->compat_chain_fsp->fsp_flags.closing) {
1288 0 : return NULL;
1289 : }
1290 782357 : return smb2req->compat_chain_fsp;
1291 : }
1292 :
1293 794659 : fsp = file_fsp_get(smb2req, persistent_id, volatile_id);
1294 794659 : if (fsp == NULL) {
1295 12168 : return NULL;
1296 : }
1297 :
1298 782491 : smb2req->compat_chain_fsp = fsp;
1299 782491 : return fsp;
1300 : }
1301 :
1302 : /****************************************************************************
1303 : Duplicate the file handle part for a DOS or FCB open.
1304 : ****************************************************************************/
1305 :
1306 113 : NTSTATUS dup_file_fsp(
1307 : struct smb_request *req,
1308 : files_struct *from,
1309 : uint32_t access_mask,
1310 : uint32_t create_options,
1311 : files_struct *to)
1312 : {
1313 : size_t new_refcount;
1314 :
1315 : /* this can never happen for print files */
1316 113 : SMB_ASSERT(from->print_file == NULL);
1317 :
1318 113 : TALLOC_FREE(to->fh);
1319 :
1320 113 : to->fh = from->fh;
1321 113 : new_refcount = fh_get_refcount(to->fh) + 1;
1322 113 : fh_set_refcount(to->fh, new_refcount);
1323 :
1324 113 : to->file_id = from->file_id;
1325 113 : to->initial_allocation_size = from->initial_allocation_size;
1326 113 : to->file_pid = from->file_pid;
1327 113 : to->vuid = from->vuid;
1328 113 : to->open_time = from->open_time;
1329 113 : to->access_mask = access_mask;
1330 113 : to->oplock_type = from->oplock_type;
1331 113 : to->fsp_flags.can_lock = from->fsp_flags.can_lock;
1332 113 : to->fsp_flags.can_read = ((access_mask & FILE_READ_DATA) != 0);
1333 113 : to->fsp_flags.can_write =
1334 226 : CAN_WRITE(from->conn) &&
1335 113 : ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
1336 113 : to->fsp_flags.modified = from->fsp_flags.modified;
1337 113 : to->fsp_flags.is_directory = from->fsp_flags.is_directory;
1338 113 : to->fsp_flags.aio_write_behind = from->fsp_flags.aio_write_behind;
1339 113 : to->fsp_flags.is_fsa = from->fsp_flags.is_fsa;
1340 113 : to->fsp_flags.is_pathref = from->fsp_flags.is_pathref;
1341 113 : to->fsp_flags.have_proc_fds = from->fsp_flags.have_proc_fds;
1342 113 : to->fsp_flags.is_dirfsp = from->fsp_flags.is_dirfsp;
1343 :
1344 113 : return fsp_set_smb_fname(to, from->fsp_name);
1345 : }
1346 :
1347 : /**
1348 : * Return a jenkins hash of a pathname on a connection.
1349 : */
1350 :
1351 10689843 : NTSTATUS file_name_hash(connection_struct *conn,
1352 : const char *name, uint32_t *p_name_hash)
1353 : {
1354 : char tmpbuf[PATH_MAX];
1355 : char *fullpath, *to_free;
1356 : ssize_t len;
1357 : TDB_DATA key;
1358 :
1359 : /* Set the hash of the full pathname. */
1360 :
1361 10689843 : if (name[0] == '/') {
1362 3533245 : strlcpy(tmpbuf, name, sizeof(tmpbuf));
1363 3533245 : fullpath = tmpbuf;
1364 3533245 : len = strlen(fullpath);
1365 3533245 : to_free = NULL;
1366 : } else {
1367 7156598 : len = full_path_tos(conn->connectpath,
1368 : name,
1369 : tmpbuf,
1370 : sizeof(tmpbuf),
1371 : &fullpath,
1372 : &to_free);
1373 : }
1374 10689843 : if (len == -1) {
1375 0 : return NT_STATUS_NO_MEMORY;
1376 : }
1377 10689843 : key = (TDB_DATA) { .dptr = (uint8_t *)fullpath, .dsize = len+1 };
1378 10689843 : *p_name_hash = tdb_jenkins_hash(&key);
1379 :
1380 10689843 : DEBUG(10,("file_name_hash: %s hash 0x%x\n",
1381 : fullpath,
1382 : (unsigned int)*p_name_hash ));
1383 :
1384 10689843 : TALLOC_FREE(to_free);
1385 10689843 : return NT_STATUS_OK;
1386 : }
1387 :
1388 10561150 : static NTSTATUS fsp_attach_smb_fname(struct files_struct *fsp,
1389 : struct smb_filename **_smb_fname)
1390 : {
1391 10561150 : struct smb_filename *smb_fname_new = *_smb_fname;
1392 10561150 : const char *name_str = NULL;
1393 10561150 : uint32_t name_hash = 0;
1394 : NTSTATUS status;
1395 :
1396 10561150 : name_str = smb_fname_str_dbg(smb_fname_new);
1397 10561150 : if (name_str == NULL) {
1398 0 : return NT_STATUS_NO_MEMORY;
1399 : }
1400 :
1401 10561150 : status = file_name_hash(fsp->conn,
1402 : name_str,
1403 : &name_hash);
1404 10561150 : if (!NT_STATUS_IS_OK(status)) {
1405 0 : return status;
1406 : }
1407 :
1408 10561150 : status = fsp_smb_fname_link(fsp,
1409 : &smb_fname_new->fsp_link,
1410 : &smb_fname_new->fsp);
1411 10561150 : if (!NT_STATUS_IS_OK(status)) {
1412 0 : return status;
1413 : }
1414 :
1415 10561150 : fsp->name_hash = name_hash;
1416 10561150 : fsp->fsp_name = smb_fname_new;
1417 10561150 : *_smb_fname = NULL;
1418 10561150 : return NT_STATUS_OK;
1419 : }
1420 :
1421 : /**
1422 : * The only way that the fsp->fsp_name field should ever be set.
1423 : */
1424 608830 : NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
1425 : const struct smb_filename *smb_fname_in)
1426 : {
1427 608830 : struct smb_filename *smb_fname_old = fsp->fsp_name;
1428 608830 : struct smb_filename *smb_fname_new = NULL;
1429 : NTSTATUS status;
1430 :
1431 608830 : smb_fname_new = cp_smb_filename(fsp, smb_fname_in);
1432 608830 : if (smb_fname_new == NULL) {
1433 0 : return NT_STATUS_NO_MEMORY;
1434 : }
1435 :
1436 608830 : status = fsp_attach_smb_fname(fsp, &smb_fname_new);
1437 608830 : if (!NT_STATUS_IS_OK(status)) {
1438 0 : TALLOC_FREE(smb_fname_new);
1439 0 : return status;
1440 : }
1441 :
1442 608830 : if (smb_fname_old != NULL) {
1443 608702 : smb_fname_fsp_unlink(smb_fname_old);
1444 608702 : TALLOC_FREE(smb_fname_old);
1445 : }
1446 :
1447 608830 : return NT_STATUS_OK;
1448 : }
1449 :
1450 7402 : size_t fsp_fullbasepath(struct files_struct *fsp, char *buf, size_t buflen)
1451 : {
1452 7402 : int len = 0;
1453 7402 : char tmp_buf[1] = {'\0'};
1454 :
1455 : /*
1456 : * Don't pass NULL buffer to snprintf (to satisfy static checker)
1457 : * Some callers will call this function with NULL for buf and
1458 : * 0 for buflen in order to get length of fullbasepath (without
1459 : * needing to allocate or write to buf)
1460 : */
1461 7402 : if (buf == NULL) {
1462 3702 : buf = tmp_buf;
1463 : }
1464 :
1465 7402 : len = snprintf(buf, buflen, "%s/%s", fsp->conn->connectpath,
1466 7402 : fsp->fsp_name->base_name);
1467 7402 : SMB_ASSERT(len>0);
1468 :
1469 7402 : return len;
1470 : }
1471 :
1472 16449 : void fsp_set_base_fsp(struct files_struct *fsp, struct files_struct *base_fsp)
1473 : {
1474 16449 : SMB_ASSERT(fsp->stream_fsp == NULL);
1475 16449 : if (base_fsp != NULL) {
1476 11725 : SMB_ASSERT(base_fsp->base_fsp == NULL);
1477 11725 : SMB_ASSERT(base_fsp->stream_fsp == NULL);
1478 : }
1479 :
1480 16449 : if (fsp->base_fsp != NULL) {
1481 4724 : SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1482 4724 : fsp->base_fsp->stream_fsp = NULL;
1483 : }
1484 :
1485 16449 : fsp->base_fsp = base_fsp;
1486 16449 : if (fsp->base_fsp != NULL) {
1487 11725 : fsp->base_fsp->stream_fsp = fsp;
1488 : }
1489 16449 : }
|