2 Unix SMB/CIFS implementation.
3 filename handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1999-2007
6 Copyright (C) Ying Chen 2000
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * New hash table stat cache code added by Ying Chen.
28 #include "system/filesys.h"
29 #include "fake_file.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "lib/util/memcache.h"
34 static NTSTATUS
get_real_filename(connection_struct
*conn
,
35 struct smb_filename
*path
,
40 static NTSTATUS
check_name(connection_struct
*conn
,
41 const struct smb_filename
*smb_fname
);
43 uint32_t ucf_flags_from_smb_request(struct smb_request
*req
)
45 uint32_t ucf_flags
= 0;
48 if (req
->posix_pathnames
) {
49 ucf_flags
|= UCF_POSIX_PATHNAMES
;
51 if (req
->flags2
& FLAGS2_DFS_PATHNAMES
) {
52 ucf_flags
|= UCF_DFS_PATHNAME
;
54 if (req
->flags2
& FLAGS2_REPARSE_PATH
) {
55 ucf_flags
|= UCF_GMT_PATHNAME
;
62 uint32_t filename_create_ucf_flags(struct smb_request
*req
, uint32_t create_disposition
)
64 uint32_t ucf_flags
= 0;
66 ucf_flags
|= ucf_flags_from_smb_request(req
);
68 switch (create_disposition
) {
75 case FILE_OVERWRITE_IF
:
76 ucf_flags
|= UCF_PREP_CREATEFILE
;
83 static NTSTATUS
build_stream_path(TALLOC_CTX
*mem_ctx
,
84 connection_struct
*conn
,
85 struct smb_filename
*smb_fname
);
87 /****************************************************************************
88 Mangle the 2nd name and check if it is then equal to the first name.
89 ****************************************************************************/
91 static bool mangled_equal(const char *name1
,
93 const struct share_params
*p
)
97 if (!name_to_8_3(name2
, mname
, False
, p
)) {
100 return strequal(name1
, mname
);
103 static NTSTATUS
check_for_dot_component(const struct smb_filename
*smb_fname
)
105 /* Ensure we catch all names with in "/."
106 this is disallowed under Windows and
107 in POSIX they've already been removed. */
108 const char *p
= strstr(smb_fname
->base_name
, "/."); /*mb safe*/
111 /* Error code within a pathname. */
112 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
113 } else if (p
[2] == '\0') {
114 /* Error code at the end of a pathname. */
115 return NT_STATUS_OBJECT_NAME_INVALID
;
121 /****************************************************************************
122 Optimization for common case where the missing part
123 is in the last component and the client already
124 sent the correct case.
125 Returns NT_STATUS_OK to mean continue the tree walk
126 (possibly with modified start pointer).
127 Any other NT_STATUS_XXX error means terminate the path
129 ****************************************************************************/
131 static NTSTATUS
check_parent_exists(TALLOC_CTX
*ctx
,
132 connection_struct
*conn
,
133 bool posix_pathnames
,
134 const struct smb_filename
*smb_fname
,
137 int *p_parent_stat_errno
)
139 char *parent_name
= NULL
;
140 struct smb_filename
*parent_fname
= NULL
;
141 const char *last_component
= NULL
;
145 if (!parent_dirname(ctx
, smb_fname
->base_name
,
148 return NT_STATUS_NO_MEMORY
;
151 if (!posix_pathnames
) {
152 if (ms_has_wild(parent_name
)) {
153 goto no_optimization_out
;
158 * If there was no parent component in
159 * smb_fname->base_name then don't do this
162 if (smb_fname
->base_name
== last_component
) {
163 goto no_optimization_out
;
166 parent_fname
= synthetic_smb_fname(ctx
,
172 if (parent_fname
== NULL
) {
173 return NT_STATUS_NO_MEMORY
;
176 ret
= vfs_stat(conn
, parent_fname
);
178 /* If the parent stat failed, just continue
179 with the normal tree walk. */
183 * Optimization. Preserving the
184 * errno from the STAT/LSTAT here
185 * will allow us to save a duplicate
186 * STAT/LSTAT system call of the parent
187 * pathname in a hot code path in the caller.
189 if (p_parent_stat_errno
!= NULL
) {
190 *p_parent_stat_errno
= errno
;
192 goto no_optimization_out
;
195 status
= check_for_dot_component(parent_fname
);
196 if (!NT_STATUS_IS_OK(status
)) {
200 /* Parent exists - set "start" to be the
201 * last component to shorten the tree walk. */
204 * Safe to use discard_const_p
205 * here as last_component points
206 * into our smb_fname->base_name.
208 *pp_start
= discard_const_p(char, last_component
);
210 /* Update dirpath. */
211 TALLOC_FREE(*pp_dirpath
);
212 *pp_dirpath
= talloc_strdup(ctx
, parent_fname
->base_name
);
214 return NT_STATUS_NO_MEMORY
;
217 DEBUG(5,("check_parent_exists: name "
218 "= %s, dirpath = %s, "
220 smb_fname
->base_name
,
229 * We must still return an *pp_dirpath
230 * initialized to ".", and a *pp_start
231 * pointing at smb_fname->base_name.
234 TALLOC_FREE(parent_name
);
235 TALLOC_FREE(parent_fname
);
237 *pp_dirpath
= talloc_strdup(ctx
, ".");
238 if (*pp_dirpath
== NULL
) {
239 return NT_STATUS_NO_MEMORY
;
242 * Safe to use discard_const_p
243 * here as by convention smb_fname->base_name
244 * is allocated off ctx.
246 *pp_start
= discard_const_p(char, smb_fname
->base_name
);
250 static bool find_snapshot_token(
251 const char *filename
,
253 const char **_next_component
,
256 const char *start
= NULL
;
257 const char *end
= NULL
;
261 start
= strstr_m(filename
, "@GMT-");
267 if ((start
> filename
) && (start
[-1] != '/')) {
268 /* the GMT-token does not start a path-component */
272 end
= strptime(start
, GMT_FORMAT
, &tm
);
274 /* Not a valid timestring. */
278 if ((end
[0] != '\0') && (end
[0] != '/')) {
280 * It is not a complete path component, i.e. the path
281 * component continues after the gmt-token.
288 unix_to_nt_time(twrp
, t
);
290 DBG_DEBUG("Extracted @GMT-Timestamp %s\n",
291 nt_time_string(talloc_tos(), *twrp
));
298 *_next_component
= end
;
303 bool extract_snapshot_token(char *fname
, uint32_t ucf_flags
, NTTIME
*twrp
)
305 const char *start
= NULL
;
306 const char *next
= NULL
;
309 bool posix_path
= (ucf_flags
& UCF_POSIX_PATHNAMES
);
310 bool msdfs_path
= (ucf_flags
& UCF_DFS_PATHNAME
);
312 if (msdfs_path
&& !posix_path
) {
314 * A raw (non-POSIX) MSDFS path looks like \server\share\path.
315 * find_snapshot_token only looks for '/' separators.
316 * Convert the separator characters in place.
318 string_replace(fname
, '\\', '/');
320 found
= find_snapshot_token(fname
, &start
, &next
, twrp
);
321 if (msdfs_path
&& !posix_path
) {
322 /* Put the original separators back. */
323 string_replace(fname
, '/', '\\');
329 remaining
= strlen(next
);
330 memmove(discard_const_p(char, start
), next
, remaining
+1);
336 * Strip a valid @GMT-token from any incoming filename path,
337 * adding any NTTIME encoded in the pathname into the
338 * twrp field of the passed in smb_fname.
340 * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
341 * at the *start* of a pathname component.
343 * If twrp is passed in then smb_fname->twrp is set to that
344 * value, and the @GMT-token part of the filename is removed
345 * and does not change the stored smb_fname->twrp.
349 NTSTATUS
canonicalize_snapshot_path(struct smb_filename
*smb_fname
,
356 smb_fname
->twrp
= twrp
;
359 if (!(ucf_flags
& UCF_GMT_PATHNAME
)) {
363 found
= extract_snapshot_token(smb_fname
->base_name
, ucf_flags
, &twrp
);
368 if (smb_fname
->twrp
== 0) {
369 smb_fname
->twrp
= twrp
;
375 static bool strnorm(char *s
, int case_default
)
377 if (case_default
== CASE_UPPER
)
378 return strupper_m(s
);
380 return strlower_m(s
);
384 * Utility function to normalize case on an incoming client filename
385 * if required on this connection struct.
386 * Performs an in-place case conversion guaranteed to stay the same size.
389 static NTSTATUS
normalize_filename_case(connection_struct
*conn
,
395 if (ucf_flags
& UCF_POSIX_PATHNAMES
) {
397 * POSIX never normalizes filename case.
401 if (!conn
->case_sensitive
) {
404 if (conn
->case_preserve
) {
407 if (conn
->short_case_preserve
) {
410 ok
= strnorm(filename
, lp_default_case(SNUM(conn
)));
412 return NT_STATUS_INVALID_PARAMETER
;
417 /****************************************************************************
418 This routine is called to convert names from the dos namespace to unix
419 namespace. It needs to handle any case conversions, mangling, format changes,
422 We assume that we have already done a chdir() to the right "root" directory
425 Conversion to basic unix format is already done in check_path_syntax().
427 Names must be relative to the root of the service - any leading /. and
428 trailing /'s should have been trimmed by check_path_syntax().
430 The function will return an NTSTATUS error if some part of the name except for
431 the last part cannot be resolved, else NT_STATUS_OK.
433 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
434 didn't get any fatal errors that should immediately terminate the calling SMB
435 processing whilst resolving.
437 If the orig_path was a stream, smb_filename->base_name will point to the base
438 filename, and smb_filename->stream_name will point to the stream name. If
439 orig_path was not a stream, then smb_filename->stream_name will be NULL.
441 On exit from unix_convert, the smb_filename->st stat struct will be populated
442 if the file exists and was found, if not this stat struct will be filled with
443 zeros (and this can be detected by checking for nlinks = 0, which can never be
445 ****************************************************************************/
449 struct connection_struct
*conn
;
450 struct smb_filename
*smb_fname
;
451 const char *orig_path
;
457 bool component_was_mangled
;
458 bool posix_pathnames
;
462 bool short_case_preserve
;
465 static NTSTATUS
unix_convert_step_search_fail(
466 struct uc_state
*state
, NTSTATUS status
)
472 * An intermediate part of the name
475 DBG_DEBUG("Intermediate [%s] missing\n",
480 * We need to return the fact that the
481 * intermediate name resolution failed.
482 * This is used to return an error of
483 * ERRbadpath rather than ERRbadfile.
484 * Some Windows applications depend on
485 * the difference between these two
490 * ENOENT, ENOTDIR and ELOOP all map
491 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
492 * in the filename walk.
494 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) ||
495 NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
) ||
496 NT_STATUS_EQUAL(status
, NT_STATUS_NOT_A_DIRECTORY
)) {
497 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
503 * ENOENT/EACCESS are the only valid errors
507 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
508 if ((state
->ucf_flags
& UCF_PREP_CREATEFILE
) == 0) {
510 * Could be a symlink pointing to
511 * a directory outside the share
512 * to which we don't have access.
513 * If so, we need to know that here
514 * so we can return the correct error code.
515 * check_name() is never called if we
516 * error out of filename_convert().
519 struct smb_filename dname
= (struct smb_filename
) {
520 .base_name
= state
->dirpath
,
521 .twrp
= state
->smb_fname
->twrp
,
524 /* handle null paths */
525 if ((dname
.base_name
== NULL
) ||
526 (dname
.base_name
[0] == '\0')) {
527 return NT_STATUS_ACCESS_DENIED
;
529 ret
= SMB_VFS_LSTAT(state
->conn
, &dname
);
531 return NT_STATUS_ACCESS_DENIED
;
533 if (!S_ISLNK(dname
.st
.st_ex_mode
)) {
534 return NT_STATUS_ACCESS_DENIED
;
536 status
= check_name(state
->conn
, &dname
);
537 if (!NT_STATUS_IS_OK(status
)) {
538 /* We know this is an intermediate path. */
539 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
541 return NT_STATUS_ACCESS_DENIED
;
544 * This is the dropbox
545 * behaviour. A dropbox is a
546 * directory with only -wx
548 * get_real_filename fails
549 * with EACCESS, it needs to
550 * list the directory. We
551 * nevertheless want to allow
552 * users creating a file.
554 status
= NT_STATUS_OK
;
558 if (!NT_STATUS_IS_OK(status
) &&
559 !NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
561 * ENOTDIR and ELOOP both map to
562 * NT_STATUS_OBJECT_PATH_NOT_FOUND
563 * in the filename walk.
565 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_A_DIRECTORY
) ||
566 NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
567 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
573 * POSIX pathnames must never call into mangling.
575 if (state
->posix_pathnames
) {
580 * Just the last part of the name doesn't exist.
581 * We need to strupper() or strlower() it as
582 * this conversion may be used for file creation
583 * purposes. Fix inspired by
584 * Thomas Neumann <t.neumann@iku-ag.de>.
586 if (!state
->case_preserve
||
587 (mangle_is_8_3(state
->name
, false,
588 state
->conn
->params
) &&
589 !state
->short_case_preserve
)) {
590 if (!strnorm(state
->name
,
591 lp_default_case(SNUM(state
->conn
)))) {
592 DBG_DEBUG("strnorm %s failed\n",
594 return NT_STATUS_INVALID_PARAMETER
;
599 * check on the mangled stack to see if we can
600 * recover the base of the filename.
603 if (mangle_is_mangled(state
->name
, state
->conn
->params
)
604 && mangle_lookup_name_from_8_3(state
->mem_ctx
,
607 state
->conn
->params
)) {
610 state
->name
- state
->smb_fname
->base_name
;
612 if (!ISDOT(state
->dirpath
)) {
613 tmp
= talloc_asprintf(
614 state
->smb_fname
, "%s/%s",
615 state
->dirpath
, unmangled
);
616 TALLOC_FREE(unmangled
);
622 DBG_ERR("talloc failed\n");
623 return NT_STATUS_NO_MEMORY
;
625 TALLOC_FREE(state
->smb_fname
->base_name
);
626 state
->smb_fname
->base_name
= tmp
;
628 state
->smb_fname
->base_name
+ name_ofs
;
629 state
->end
= state
->name
+ strlen(state
->name
);
634 DBG_DEBUG("New file [%s]\n", state
->name
);
639 static NTSTATUS
unix_convert_step_stat(struct uc_state
*state
)
641 struct smb_filename dname
;
643 char *found_name
= NULL
;
648 * Check if the name exists up to this point.
651 DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state
->smb_fname
));
653 ret
= vfs_stat(state
->conn
, state
->smb_fname
);
656 * It exists. it must either be a directory or this must
657 * be the last part of the path for it to be OK.
659 if (state
->end
&& !S_ISDIR(state
->smb_fname
->st
.st_ex_mode
)) {
661 * An intermediate part of the name isn't
664 DBG_DEBUG("Not a dir [%s]\n", state
->name
);
667 * We need to return the fact that the
668 * intermediate name resolution failed. This
669 * is used to return an error of ERRbadpath
670 * rather than ERRbadfile. Some Windows
671 * applications depend on the difference between
674 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
679 /* Stat failed - ensure we don't use it. */
680 SET_STAT_INVALID(state
->smb_fname
->st
);
682 if (state
->posix_pathnames
) {
684 * For posix_pathnames, we're done.
685 * Don't blunder into the
686 * get_real_filename() codepath as they may
687 * be doing case insensitive lookups. So when
688 * creating a new POSIX directory Foo they might
691 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
693 if (state
->end
!= NULL
) {
694 const char *morepath
= NULL
;
696 * If this is intermediate we must
697 * restore the full path.
701 * If there are any more components
702 * after the failed LSTAT we cannot
705 morepath
= strchr(state
->end
+ 1, '/');
706 if (morepath
!= NULL
) {
707 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
710 if (errno
== ENOENT
) {
711 /* New file or directory. */
715 if ((errno
== EACCES
) &&
716 (state
->ucf_flags
& UCF_PREP_CREATEFILE
)) {
717 /* POSIX Dropbox case. */
722 return map_nt_error_from_unix(errno
);
726 * Reset errno so we can detect
727 * directory open errors.
732 * Try to find this part of the path in the directory.
735 dname
= (struct smb_filename
) {
736 .base_name
= state
->dirpath
,
737 .twrp
= state
->smb_fname
->twrp
,
740 /* handle null paths */
741 if ((dname
.base_name
== NULL
) || (dname
.base_name
[0] == '\0')) {
742 dname
.base_name
= dot
;
745 status
= get_real_filename(state
->conn
,
750 if (!NT_STATUS_IS_OK(status
)) {
751 return unix_convert_step_search_fail(state
, status
);
755 * Restore the rest of the string. If the string was
756 * mangled the size may have changed.
761 state
->name
- state
->smb_fname
->base_name
;
763 if (!ISDOT(state
->dirpath
)) {
764 tmp
= talloc_asprintf(state
->smb_fname
,
765 "%s/%s/%s", state
->dirpath
,
766 found_name
, state
->end
+1);
769 tmp
= talloc_asprintf(state
->smb_fname
,
774 DBG_ERR("talloc_asprintf failed\n");
775 return NT_STATUS_NO_MEMORY
;
777 TALLOC_FREE(state
->smb_fname
->base_name
);
778 state
->smb_fname
->base_name
= tmp
;
779 state
->name
= state
->smb_fname
->base_name
+ name_ofs
;
780 state
->end
= state
->name
+ strlen(found_name
);
785 state
->name
- state
->smb_fname
->base_name
;
787 if (!ISDOT(state
->dirpath
)) {
788 tmp
= talloc_asprintf(state
->smb_fname
,
789 "%s/%s", state
->dirpath
,
792 tmp
= talloc_strdup(state
->smb_fname
,
796 DBG_ERR("talloc failed\n");
797 return NT_STATUS_NO_MEMORY
;
799 TALLOC_FREE(state
->smb_fname
->base_name
);
800 state
->smb_fname
->base_name
= tmp
;
801 state
->name
= state
->smb_fname
->base_name
+ name_ofs
;
804 * We just scanned for, and found the end of
805 * the path. We must return a valid stat struct
809 ret
= vfs_stat(state
->conn
, state
->smb_fname
);
811 SET_STAT_INVALID(state
->smb_fname
->st
);
815 TALLOC_FREE(found_name
);
819 static NTSTATUS
unix_convert_step(struct uc_state
*state
)
824 * Pinpoint the end of this section of the filename.
826 /* mb safe. '/' can't be in any encoded char. */
827 state
->end
= strchr(state
->name
, '/');
830 * Chop the name at this point.
832 if (state
->end
!= NULL
) {
836 DBG_DEBUG("dirpath [%s] name [%s]\n", state
->dirpath
, state
->name
);
838 /* The name cannot have a component of "." */
840 if (ISDOT(state
->name
)) {
841 if (state
->end
== NULL
) {
842 /* Error code at the end of a pathname. */
843 return NT_STATUS_OBJECT_NAME_INVALID
;
845 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
848 status
= unix_convert_step_stat(state
);
849 if (!NT_STATUS_IS_OK(status
)) {
857 * Add to the dirpath that we have resolved so far.
860 if (!ISDOT(state
->dirpath
)) {
861 char *tmp
= talloc_asprintf(state
->mem_ctx
,
862 "%s/%s", state
->dirpath
, state
->name
);
864 DBG_ERR("talloc_asprintf failed\n");
865 return NT_STATUS_NO_MEMORY
;
867 TALLOC_FREE(state
->dirpath
);
868 state
->dirpath
= tmp
;
871 TALLOC_FREE(state
->dirpath
);
872 if (!(state
->dirpath
= talloc_strdup(state
->mem_ctx
,state
->name
))) {
873 DBG_ERR("talloc_strdup failed\n");
874 return NT_STATUS_NO_MEMORY
;
879 * Cache the dirpath thus far. Don't cache a name with mangled
880 * components as this can change the size.
882 if(!state
->component_was_mangled
) {
883 stat_cache_add(state
->orig_path
,
885 state
->smb_fname
->twrp
,
886 state
->case_sensitive
);
890 * Restore the / that we wiped out earlier.
892 if (state
->end
!= NULL
) {
899 NTSTATUS
unix_convert(TALLOC_CTX
*mem_ctx
,
900 connection_struct
*conn
,
901 const char *orig_path
,
903 struct smb_filename
**smb_fname_out
,
906 struct uc_state uc_state
;
907 struct uc_state
*state
= &uc_state
;
910 int parent_stat_errno
= 0;
912 *state
= (struct uc_state
) {
915 .orig_path
= orig_path
,
916 .ucf_flags
= ucf_flags
,
917 .posix_pathnames
= (ucf_flags
& UCF_POSIX_PATHNAMES
),
918 .case_sensitive
= conn
->case_sensitive
,
919 .case_preserve
= conn
->case_preserve
,
920 .short_case_preserve
= conn
->short_case_preserve
,
923 *smb_fname_out
= NULL
;
925 if (state
->posix_pathnames
) {
926 /* POSIX means ignore case settings on share. */
927 state
->case_sensitive
= true;
928 state
->case_preserve
= true;
929 state
->short_case_preserve
= true;
932 state
->smb_fname
= talloc_zero(state
->mem_ctx
, struct smb_filename
);
933 if (state
->smb_fname
== NULL
) {
934 return NT_STATUS_NO_MEMORY
;
937 if (state
->conn
->printer
) {
938 /* we don't ever use the filenames on a printer share as a
939 filename - so don't convert them */
940 state
->smb_fname
->base_name
= talloc_strdup(
941 state
->smb_fname
, state
->orig_path
);
942 if (state
->smb_fname
->base_name
== NULL
) {
943 status
= NT_STATUS_NO_MEMORY
;
949 state
->smb_fname
->flags
= state
->posix_pathnames
? SMB_FILENAME_POSIX_PATH
: 0;
951 DBG_DEBUG("Called on file [%s]\n", state
->orig_path
);
953 if (state
->orig_path
[0] == '/') {
954 DBG_ERR("Path [%s] starts with '/'\n", state
->orig_path
);
955 return NT_STATUS_OBJECT_NAME_INVALID
;
958 /* Start with the full orig_path as given by the caller. */
959 state
->smb_fname
->base_name
= talloc_strdup(
960 state
->smb_fname
, state
->orig_path
);
961 if (state
->smb_fname
->base_name
== NULL
) {
962 DBG_ERR("talloc_strdup failed\n");
963 status
= NT_STATUS_NO_MEMORY
;
967 /* Canonicalize any @GMT- paths. */
968 status
= canonicalize_snapshot_path(state
->smb_fname
, ucf_flags
, twrp
);
969 if (!NT_STATUS_IS_OK(status
)) {
974 * If we trimmed down to a single '\0' character
975 * then we should use the "." directory to avoid
976 * searching the cache, but not if we are in a
978 * As we know this is valid we can return true here.
981 if (state
->smb_fname
->base_name
[0] == '\0') {
982 state
->smb_fname
->base_name
= talloc_strdup(state
->smb_fname
, ".");
983 if (state
->smb_fname
->base_name
== NULL
) {
984 status
= NT_STATUS_NO_MEMORY
;
987 if (SMB_VFS_STAT(state
->conn
, state
->smb_fname
) != 0) {
988 status
= map_nt_error_from_unix(errno
);
991 DBG_DEBUG("conversion finished [] -> [%s]\n",
992 state
->smb_fname
->base_name
);
996 if (state
->orig_path
[0] == '.' && (state
->orig_path
[1] == '/' ||
997 state
->orig_path
[1] == '\0')) {
998 /* Start of pathname can't be "." only. */
999 if (state
->orig_path
[1] == '\0' || state
->orig_path
[2] == '\0') {
1000 status
= NT_STATUS_OBJECT_NAME_INVALID
;
1002 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1008 * Large directory fix normalization. If we're case sensitive, and
1009 * the case preserving parameters are set to "no", normalize the case of
1010 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
1011 * This is in conflict with the current (3.0.20) man page, but is
1012 * what people expect from the "large directory howto". I'll update
1013 * the man page. Thanks to jht@samba.org for finding this. JRA.
1016 status
= normalize_filename_case(state
->conn
,
1017 state
->smb_fname
->base_name
,
1019 if (!NT_STATUS_IS_OK(status
)) {
1020 DBG_ERR("normalize_filename_case %s failed\n",
1021 state
->smb_fname
->base_name
);
1026 * Strip off the stream, and add it back when we're done with the
1029 if (!state
->posix_pathnames
) {
1030 state
->stream
= strchr_m(state
->smb_fname
->base_name
, ':');
1032 if (state
->stream
!= NULL
) {
1033 char *tmp
= talloc_strdup(state
->smb_fname
, state
->stream
);
1035 status
= NT_STATUS_NO_MEMORY
;
1039 * Since this is actually pointing into
1040 * smb_fname->base_name this truncates base_name.
1042 *state
->stream
= '\0';
1043 state
->stream
= tmp
;
1045 if (state
->smb_fname
->base_name
[0] == '\0') {
1047 * orig_name was just a stream name.
1048 * This is a stream on the root of
1049 * the share. Replace base_name with
1052 state
->smb_fname
->base_name
=
1053 talloc_strdup(state
->smb_fname
, ".");
1054 if (state
->smb_fname
->base_name
== NULL
) {
1055 status
= NT_STATUS_NO_MEMORY
;
1058 if (SMB_VFS_STAT(state
->conn
, state
->smb_fname
) != 0) {
1059 status
= map_nt_error_from_unix(errno
);
1062 /* dirpath must exist. */
1063 state
->dirpath
= talloc_strdup(state
->mem_ctx
,".");
1064 if (state
->dirpath
== NULL
) {
1065 status
= NT_STATUS_NO_MEMORY
;
1068 DBG_INFO("conversion finished [%s] -> [%s]\n",
1070 state
->smb_fname
->base_name
);
1076 state
->name
= state
->smb_fname
->base_name
;
1079 * If we're providing case insensitive semantics or
1080 * the underlying filesystem is case insensitive,
1081 * then a case-normalized hit in the stat-cache is
1082 * authoritative. JRA.
1084 * Note: We're only checking base_name. The stream_name will be
1085 * added and verified in build_stream_path().
1088 if (!state
->case_sensitive
||
1089 !(state
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
1093 found
= stat_cache_lookup(state
->conn
,
1094 &state
->smb_fname
->base_name
,
1097 state
->smb_fname
->twrp
,
1098 &state
->smb_fname
->st
);
1100 * stat_cache_lookup() allocates on talloc_tos() even
1101 * when !found, reparent correctly
1103 talloc_steal(state
->smb_fname
, state
->smb_fname
->base_name
);
1104 talloc_steal(state
->mem_ctx
, state
->dirpath
);
1112 * Make sure "dirpath" is an allocated string, we use this for
1113 * building the directories with talloc_asprintf and free it.
1116 if (state
->dirpath
== NULL
) {
1117 state
->dirpath
= talloc_strdup(state
->mem_ctx
,".");
1118 if (state
->dirpath
== NULL
) {
1119 DBG_ERR("talloc_strdup failed\n");
1120 status
= NT_STATUS_NO_MEMORY
;
1126 * If we have a wildcard we must walk the path to
1127 * find where the error is, even if case sensitive
1131 if (!state
->posix_pathnames
) {
1132 /* POSIX pathnames have no wildcards. */
1133 bool name_has_wildcard
= ms_has_wild(state
->smb_fname
->base_name
);
1134 if (name_has_wildcard
) {
1135 /* Wildcard not valid anywhere. */
1136 status
= NT_STATUS_OBJECT_NAME_INVALID
;
1141 DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
1142 state
->smb_fname
->base_name
, state
->dirpath
, state
->name
);
1145 * stat the name - if it exists then we can add the stream back (if
1146 * there was one) and be done!
1149 ret
= vfs_stat(state
->conn
, state
->smb_fname
);
1151 status
= check_for_dot_component(state
->smb_fname
);
1152 if (!NT_STATUS_IS_OK(status
)) {
1155 /* Add the path (not including the stream) to the cache. */
1156 stat_cache_add(state
->orig_path
,
1157 state
->smb_fname
->base_name
,
1158 state
->smb_fname
->twrp
,
1159 state
->case_sensitive
);
1160 DBG_DEBUG("Conversion of base_name finished "
1162 state
->orig_path
, state
->smb_fname
->base_name
);
1166 /* Stat failed - ensure we don't use it. */
1167 SET_STAT_INVALID(state
->smb_fname
->st
);
1170 * Note: we must continue processing a path if we get EACCES
1171 * from stat. With NFS4 permissions the file might be lacking
1172 * READ_ATTR, but if the parent has LIST permissions we can
1173 * resolve the path in the path traversal loop down below.
1176 if (errno
== ENOENT
) {
1177 /* Optimization when creating a new file - only
1178 the last component doesn't exist.
1179 NOTE : check_parent_exists() doesn't preserve errno.
1181 int saved_errno
= errno
;
1182 status
= check_parent_exists(state
->mem_ctx
,
1184 state
->posix_pathnames
,
1188 &parent_stat_errno
);
1189 errno
= saved_errno
;
1190 if (!NT_STATUS_IS_OK(status
)) {
1196 * A special case - if we don't have any wildcards or mangling chars and are case
1197 * sensitive or the underlying filesystem is case insensitive then searching
1200 * NB. As POSIX sets state->case_sensitive as
1201 * true we will never call into mangle_is_mangled() here.
1204 if ((state
->case_sensitive
|| !(state
->conn
->fs_capabilities
&
1205 FILE_CASE_SENSITIVE_SEARCH
)) &&
1206 !mangle_is_mangled(state
->smb_fname
->base_name
, state
->conn
->params
)) {
1208 status
= check_for_dot_component(state
->smb_fname
);
1209 if (!NT_STATUS_IS_OK(status
)) {
1214 * The stat failed. Could be ok as it could be
1218 if (errno
== ENOTDIR
|| errno
== ELOOP
) {
1219 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1221 } else if (errno
== ENOENT
) {
1223 * Was it a missing last component ?
1224 * or a missing intermediate component ?
1228 * For this code path we can guarantee that
1229 * we have gone through check_parent_exists()
1230 * and it returned NT_STATUS_OK.
1232 * Either there was no parent component (".")
1233 * parent_stat_errno == 0 and we have a missing
1234 * last component here.
1236 * OR check_parent_exists() called STAT/LSTAT
1237 * and if it failed parent_stat_errno has been
1238 * set telling us if the parent existed or not.
1240 * Either way we can avoid another STAT/LSTAT
1241 * system call on the parent here.
1243 if (parent_stat_errno
== ENOTDIR
||
1244 parent_stat_errno
== ENOENT
||
1245 parent_stat_errno
== ELOOP
) {
1246 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1251 * Missing last component is ok - new file.
1252 * Also deal with permission denied elsewhere.
1253 * Just drop out to done.
1260 * is_mangled() was changed to look at an entire pathname, not
1261 * just a component. JRA.
1264 if (state
->posix_pathnames
) {
1266 * POSIX names are never mangled and we must not
1267 * call into mangling functions.
1269 state
->component_was_mangled
= false;
1270 } else if (mangle_is_mangled(state
->name
, state
->conn
->params
)) {
1271 state
->component_was_mangled
= true;
1275 * Now we need to recursively match the name against the real
1276 * directory structure.
1280 * Match each part of the path name separately, trying the names
1281 * as is first, then trying to scan the directory for matching names.
1284 for (; state
->name
; state
->name
= (state
->end
? state
->end
+ 1:(char *)NULL
)) {
1285 status
= unix_convert_step(state
);
1286 if (!NT_STATUS_IS_OK(status
)) {
1287 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_MEMORY
)) {
1298 * Cache the full path. Don't cache a name with mangled or wildcard
1299 * components as this can change the size.
1302 if(!state
->component_was_mangled
) {
1303 stat_cache_add(state
->orig_path
,
1304 state
->smb_fname
->base_name
,
1305 state
->smb_fname
->twrp
,
1306 state
->case_sensitive
);
1310 * The name has been resolved.
1314 /* Add back the stream if one was stripped off originally. */
1315 if (state
->stream
!= NULL
) {
1316 state
->smb_fname
->stream_name
= state
->stream
;
1318 /* Check path now that the base_name has been converted. */
1319 status
= build_stream_path(state
->mem_ctx
, state
->conn
, state
->smb_fname
);
1320 if (!NT_STATUS_IS_OK(status
)) {
1325 DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
1326 state
->orig_path
, smb_fname_str_dbg(state
->smb_fname
));
1328 TALLOC_FREE(state
->dirpath
);
1329 *smb_fname_out
= state
->smb_fname
;
1330 return NT_STATUS_OK
;
1332 DBG_DEBUG("Conversion failed: dirpath [%s] name [%s]\n",
1333 state
->dirpath
, state
->name
);
1334 if ((state
->dirpath
!= NULL
) && !ISDOT(state
->dirpath
)) {
1335 state
->smb_fname
->base_name
= talloc_asprintf(
1341 state
->smb_fname
->base_name
= talloc_strdup(
1342 state
->smb_fname
, state
->name
);
1344 if (state
->smb_fname
->base_name
== NULL
) {
1345 DBG_ERR("talloc_asprintf failed\n");
1346 status
= NT_STATUS_NO_MEMORY
;
1350 *smb_fname_out
= state
->smb_fname
;
1351 TALLOC_FREE(state
->dirpath
);
1354 TALLOC_FREE(state
->smb_fname
);
1358 /****************************************************************************
1359 Ensure a path is not vetoed.
1360 ****************************************************************************/
1362 static NTSTATUS
check_veto_path(connection_struct
*conn
,
1363 const struct smb_filename
*smb_fname
)
1365 const char *name
= smb_fname
->base_name
;
1367 if (IS_VETO_PATH(conn
, name
)) {
1368 /* Is it not dot or dot dot. */
1369 if (!(ISDOT(name
) || ISDOTDOT(name
))) {
1370 DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1372 return map_nt_error_from_unix(ENOENT
);
1375 return NT_STATUS_OK
;
1378 /****************************************************************************
1379 Check a filename - possibly calling check_reduced_name.
1380 This is called by every routine before it allows an operation on a filename.
1381 It does any final confirmation necessary to ensure that the filename is
1382 a valid one for the user to access.
1383 ****************************************************************************/
1385 static NTSTATUS
check_name(connection_struct
*conn
,
1386 const struct smb_filename
*smb_fname
)
1388 NTSTATUS status
= check_veto_path(conn
, smb_fname
);
1390 if (!NT_STATUS_IS_OK(status
)) {
1394 if (!lp_widelinks(SNUM(conn
)) || !lp_follow_symlinks(SNUM(conn
))) {
1395 status
= check_reduced_name(conn
, NULL
, smb_fname
);
1396 if (!NT_STATUS_IS_OK(status
)) {
1397 DEBUG(5,("check_name: name %s failed with %s\n",
1398 smb_fname
->base_name
,
1399 nt_errstr(status
)));
1404 return NT_STATUS_OK
;
1407 /****************************************************************************
1408 Check if two filenames are equal.
1409 This needs to be careful about whether we are case sensitive.
1410 ****************************************************************************/
1412 static bool fname_equal(const char *name1
, const char *name2
,
1413 bool case_sensitive
)
1415 /* Normal filename handling */
1416 if (case_sensitive
) {
1417 return(strcmp(name1
,name2
) == 0);
1420 return(strequal(name1
,name2
));
1423 static bool sname_equal(const char *name1
, const char *name2
,
1424 bool case_sensitive
)
1427 const char *s1
= NULL
;
1428 const char *s2
= NULL
;
1431 const char *e1
= NULL
;
1432 const char *e2
= NULL
;
1436 match
= fname_equal(name1
, name2
, case_sensitive
);
1441 if (name1
[0] != ':') {
1444 if (name2
[0] != ':') {
1448 e1
= strchr(s1
, ':');
1452 n1
= PTR_DIFF(e1
, s1
);
1455 e2
= strchr(s2
, ':');
1459 n2
= PTR_DIFF(e2
, s2
);
1462 /* Normal filename handling */
1463 if (case_sensitive
) {
1464 return (strncmp(s1
, s2
, n1
) == 0);
1468 * We can't use strnequal() here
1469 * as it takes the number of codepoints
1470 * and not the number of bytes.
1472 * So we make a copy before calling
1475 * Note that we TALLOC_FREE() in reverse order
1476 * in order to avoid memory fragmentation.
1479 c1
= talloc_strndup(talloc_tos(), s1
, n1
);
1480 c2
= talloc_strndup(talloc_tos(), s2
, n2
);
1481 if (c1
== NULL
|| c2
== NULL
) {
1484 return (strncmp(s1
, s2
, n1
) == 0);
1487 match
= strequal(c1
, c2
);
1493 /****************************************************************************
1494 Scan a directory to find a filename, matching without case sensitivity.
1495 If the name looks like a mangled name then try via the mangling functions
1496 ****************************************************************************/
1498 NTSTATUS
get_real_filename_full_scan_at(struct files_struct
*dirfsp
,
1501 TALLOC_CTX
*mem_ctx
,
1504 struct connection_struct
*conn
= dirfsp
->conn
;
1505 struct smb_Dir
*cur_dir
= NULL
;
1506 const char *dname
= NULL
;
1507 char *talloced
= NULL
;
1508 char *unmangled_name
= NULL
;
1512 /* If we have a case-sensitive filesystem, it doesn't do us any
1513 * good to search for a name. If a case variation of the name was
1514 * there, then the original stat(2) would have found it.
1516 if (!mangled
&& !(conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
)) {
1517 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1521 * The incoming name can be mangled, and if we de-mangle it
1522 * here it will not compare correctly against the filename (name2)
1523 * read from the directory and then mangled by the name_to_8_3()
1524 * call. We need to mangle both names or neither.
1527 * Fix for bug found by Dina Fine. If in case sensitive mode then
1528 * the mangle cache is no good (3 letter extension could be wrong
1529 * case - so don't demangle in this case - leave as mangled and
1530 * allow the mangling of the directory entry read (which is done
1531 * case insensitively) to match instead. This will lead to more
1532 * false positive matches but we fail completely without it. JRA.
1535 if (mangled
&& !conn
->case_sensitive
) {
1536 mangled
= !mangle_lookup_name_from_8_3(talloc_tos(), name
,
1540 /* Name is now unmangled. */
1541 name
= unmangled_name
;
1545 /* open the directory */
1546 status
= OpenDir_from_pathref(talloc_tos(), dirfsp
, NULL
, 0, &cur_dir
);
1547 if (!NT_STATUS_IS_OK(status
)) {
1548 DBG_NOTICE("scan dir didn't open dir [%s]: %s\n",
1549 fsp_str_dbg(dirfsp
),
1551 TALLOC_FREE(unmangled_name
);
1555 /* now scan for matching names */
1557 while ((dname
= ReadDirName(cur_dir
, &curpos
, NULL
, &talloced
))) {
1559 /* Is it dot or dot dot. */
1560 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
1561 TALLOC_FREE(talloced
);
1566 * At this point dname is the unmangled name.
1567 * name is either mangled or not, depending on the state
1568 * of the "mangled" variable. JRA.
1572 * Check mangled name against mangled name, or unmangled name
1573 * against unmangled name.
1576 if ((mangled
&& mangled_equal(name
,dname
,conn
->params
)) ||
1577 fname_equal(name
, dname
, conn
->case_sensitive
)) {
1578 /* we've found the file, change it's name and return */
1579 *found_name
= talloc_strdup(mem_ctx
, dname
);
1580 TALLOC_FREE(unmangled_name
);
1581 TALLOC_FREE(cur_dir
);
1583 TALLOC_FREE(talloced
);
1584 return NT_STATUS_NO_MEMORY
;
1586 TALLOC_FREE(talloced
);
1587 return NT_STATUS_OK
;
1589 TALLOC_FREE(talloced
);
1592 TALLOC_FREE(unmangled_name
);
1593 TALLOC_FREE(cur_dir
);
1594 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1597 NTSTATUS
get_real_filename_full_scan(connection_struct
*conn
,
1601 TALLOC_CTX
*mem_ctx
,
1604 struct smb_filename
*smb_dname
= NULL
;
1607 /* handle null paths */
1608 if ((path
== NULL
) || (*path
== 0)) {
1612 status
= synthetic_pathref(
1621 if (!NT_STATUS_IS_OK(status
)) {
1625 status
= get_real_filename_full_scan_at(
1626 smb_dname
->fsp
, name
, mangled
, mem_ctx
, found_name
);
1628 TALLOC_FREE(smb_dname
);
1632 /****************************************************************************
1633 Wrapper around the vfs get_real_filename and the full directory scan
1635 ****************************************************************************/
1637 NTSTATUS
get_real_filename_at(struct files_struct
*dirfsp
,
1639 TALLOC_CTX
*mem_ctx
,
1642 struct connection_struct
*conn
= dirfsp
->conn
;
1646 mangled
= mangle_is_mangled(name
, conn
->params
);
1649 status
= get_real_filename_full_scan_at(
1650 dirfsp
, name
, mangled
, mem_ctx
, found_name
);
1654 /* Try the vfs first to take advantage of case-insensitive stat. */
1655 status
= SMB_VFS_GET_REAL_FILENAME_AT(
1656 dirfsp
->conn
, dirfsp
, name
, mem_ctx
, found_name
);
1659 * If the case-insensitive stat was successful, or returned an error
1660 * other than EOPNOTSUPP then there is no need to fall back on the
1661 * full directory scan.
1663 if (NT_STATUS_IS_OK(status
) ||
1664 !NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)) {
1668 status
= get_real_filename_full_scan_at(
1669 dirfsp
, name
, mangled
, mem_ctx
, found_name
);
1674 * Create the memcache-key for GETREALFILENAME_CACHE: This supplements
1675 * the stat cache for the last component to be looked up. Cache
1676 * contents is the correctly capitalized translation of the parameter
1677 * "name" as it exists on disk. This is indexed by inode of the dirfsp
1678 * and name, and contrary to stat_cahce_lookup() it does not
1679 * vfs_stat() the last component. This will be taken care of by an
1680 * attempt to do a openat_pathref_fsp().
1682 static bool get_real_filename_cache_key(
1683 TALLOC_CTX
*mem_ctx
,
1684 struct files_struct
*dirfsp
,
1688 struct file_id fid
= vfs_file_id_from_sbuf(
1689 dirfsp
->conn
, &dirfsp
->fsp_name
->st
);
1691 uint8_t *key
= NULL
;
1692 size_t namelen
, keylen
;
1694 upper
= talloc_strdup_upper(mem_ctx
, name
);
1695 if (upper
== NULL
) {
1698 namelen
= talloc_get_size(upper
);
1700 keylen
= namelen
+ sizeof(fid
);
1701 if (keylen
< sizeof(fid
)) {
1706 key
= talloc_size(mem_ctx
, keylen
);
1712 memcpy(key
, &fid
, sizeof(fid
));
1713 memcpy(key
+ sizeof(fid
), upper
, namelen
);
1716 *_key
= (DATA_BLOB
) { .data
= key
, .length
= keylen
, };
1720 static NTSTATUS
get_real_filename(connection_struct
*conn
,
1721 struct smb_filename
*path
,
1723 TALLOC_CTX
*mem_ctx
,
1726 struct smb_filename
*smb_dname
= NULL
;
1729 smb_dname
= cp_smb_filename_nostream(talloc_tos(), path
);
1730 if (smb_dname
== NULL
) {
1731 return NT_STATUS_NO_MEMORY
;
1735 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_dname
);
1737 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) &&
1738 S_ISLNK(smb_dname
->st
.st_ex_mode
)) {
1739 status
= NT_STATUS_STOPPED_ON_SYMLINK
;
1742 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) &&
1743 (smb_dname
->twrp
!= 0)) {
1745 * Retry looking at the non-snapshot path, copying the
1746 * fallback mechanism from vfs_shadow_copy2.c when
1747 * shadow_copy2_convert() fails. This path-based
1748 * routine get_real_filename() should go away and be
1749 * replaced with a fd-based one, so spoiling it with a
1750 * shadow_copy2 specific mechanism should not be too
1753 smb_dname
->twrp
= 0;
1757 if (!NT_STATUS_IS_OK(status
)) {
1758 DBG_DEBUG("openat_pathref_fsp(%s) failed: %s\n",
1759 smb_fname_str_dbg(smb_dname
),
1763 * ENOTDIR and ELOOP both map to
1764 * NT_STATUS_OBJECT_PATH_NOT_FOUND in the filename
1767 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_A_DIRECTORY
) ||
1768 NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
1769 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1775 status
= get_real_filename_at(
1776 smb_dname
->fsp
, name
, mem_ctx
, found_name
);
1777 TALLOC_FREE(smb_dname
);
1781 static NTSTATUS
build_stream_path(TALLOC_CTX
*mem_ctx
,
1782 connection_struct
*conn
,
1783 struct smb_filename
*smb_fname
)
1786 unsigned int i
, num_streams
= 0;
1787 struct stream_struct
*streams
= NULL
;
1788 struct smb_filename
*pathref
= NULL
;
1790 if (SMB_VFS_STAT(conn
, smb_fname
) == 0) {
1791 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname
)));
1792 return NT_STATUS_OK
;
1795 if (errno
!= ENOENT
) {
1796 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno
)));
1797 status
= map_nt_error_from_unix(errno
);
1801 if (smb_fname
->fsp
== NULL
) {
1802 status
= synthetic_pathref(mem_ctx
,
1804 smb_fname
->base_name
,
1810 if (!NT_STATUS_IS_OK(status
)) {
1811 if (NT_STATUS_EQUAL(status
,
1812 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1813 TALLOC_FREE(pathref
);
1814 SET_STAT_INVALID(smb_fname
->st
);
1815 return NT_STATUS_OK
;
1817 DBG_DEBUG("synthetic_pathref failed: %s\n",
1822 pathref
= smb_fname
;
1825 /* Fall back to a case-insensitive scan of all streams on the file. */
1826 status
= vfs_fstreaminfo(pathref
->fsp
, mem_ctx
,
1827 &num_streams
, &streams
);
1828 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1829 SET_STAT_INVALID(smb_fname
->st
);
1830 TALLOC_FREE(pathref
);
1831 return NT_STATUS_OK
;
1834 if (!NT_STATUS_IS_OK(status
)) {
1835 DEBUG(10, ("vfs_fstreaminfo failed: %s\n", nt_errstr(status
)));
1839 for (i
=0; i
<num_streams
; i
++) {
1840 bool equal
= sname_equal(
1841 smb_fname
->stream_name
,
1843 conn
->case_sensitive
);
1845 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
1846 smb_fname
->stream_name
,
1848 equal
? "" : "not ");
1855 /* Couldn't find the stream. */
1856 if (i
== num_streams
) {
1857 SET_STAT_INVALID(smb_fname
->st
);
1858 TALLOC_FREE(pathref
);
1859 TALLOC_FREE(streams
);
1860 return NT_STATUS_OK
;
1863 DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1864 smb_fname
->stream_name
, streams
[i
].name
));
1867 TALLOC_FREE(smb_fname
->stream_name
);
1868 smb_fname
->stream_name
= talloc_strdup(smb_fname
, streams
[i
].name
);
1869 if (smb_fname
->stream_name
== NULL
) {
1870 status
= NT_STATUS_NO_MEMORY
;
1874 SET_STAT_INVALID(smb_fname
->st
);
1876 if (SMB_VFS_STAT(conn
, smb_fname
) == 0) {
1877 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname
)));
1879 status
= NT_STATUS_OK
;
1881 TALLOC_FREE(pathref
);
1882 TALLOC_FREE(streams
);
1887 * Lightweight function to just get last component
1888 * for rename / enumerate directory calls.
1891 char *get_original_lcomp(TALLOC_CTX
*ctx
,
1892 connection_struct
*conn
,
1893 const char *filename_in
,
1896 struct smb_filename
*smb_fname
= NULL
;
1897 char *last_slash
= NULL
;
1903 if (ucf_flags
& UCF_DFS_PATHNAME
) {
1904 status
= dfs_redirect(ctx
,
1908 !conn
->sconn
->using_smb2
,
1911 if (!NT_STATUS_IS_OK(status
)) {
1912 DBG_DEBUG("dfs_redirect "
1913 "failed for name %s with %s\n",
1918 filename_in
= fname
;
1919 ucf_flags
&= ~UCF_DFS_PATHNAME
;
1923 * NB. We don't need to care about
1924 * is_fake_file_path(filename_in) here as these
1925 * code paths don't ever return original_lcomp
1929 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1931 * Ensure we don't return a @GMT
1932 * value as the last component.
1934 smb_fname
= synthetic_smb_fname(ctx
,
1940 if (smb_fname
== NULL
) {
1944 status
= canonicalize_snapshot_path(smb_fname
,
1947 if (!NT_STATUS_IS_OK(status
)) {
1949 TALLOC_FREE(smb_fname
);
1952 filename_in
= smb_fname
->base_name
;
1954 last_slash
= strrchr(filename_in
, '/');
1955 if (last_slash
!= NULL
) {
1956 orig_lcomp
= talloc_strdup(ctx
, last_slash
+1);
1958 orig_lcomp
= talloc_strdup(ctx
, filename_in
);
1960 /* We're done with any temp names here. */
1961 TALLOC_FREE(smb_fname
);
1963 if (orig_lcomp
== NULL
) {
1966 status
= normalize_filename_case(conn
, orig_lcomp
, ucf_flags
);
1967 if (!NT_STATUS_IS_OK(status
)) {
1968 TALLOC_FREE(orig_lcomp
);
1975 * Go through all the steps to validate a filename.
1977 * @param ctx talloc_ctx to allocate memory with.
1978 * @param conn connection struct for vfs calls.
1979 * @param smbreq SMB request if we're using privileges.
1980 * @param name_in The unconverted name.
1981 * @param ucf_flags flags to pass through to unix_convert().
1982 * @param twrp Optional VSS time
1983 * @param p_cont_wcard If not NULL, will be set to true if the dfs path
1984 * resolution detects a wildcard.
1985 * @param _smb_fname The final converted name will be allocated if the
1986 * return is NT_STATUS_OK.
1988 * @return NT_STATUS_OK if all operations completed successfully, appropriate
1991 NTSTATUS
filename_convert(TALLOC_CTX
*ctx
,
1992 connection_struct
*conn
,
1993 const char *name_in
,
1996 struct smb_filename
**_smb_fname
)
1998 struct smb_filename
*smb_fname
= NULL
;
2003 if (ucf_flags
& UCF_DFS_PATHNAME
) {
2005 NTTIME dfs_twrp
= 0;
2006 status
= dfs_redirect(ctx
, conn
,
2009 !conn
->sconn
->using_smb2
,
2012 if (!NT_STATUS_IS_OK(status
)) {
2013 DBG_DEBUG("dfs_redirect "
2014 "failed for name %s with %s\n",
2020 ucf_flags
&= ~UCF_DFS_PATHNAME
;
2021 if (twrp
== 0 && dfs_twrp
!= 0) {
2026 if (is_fake_file_path(name_in
)) {
2027 smb_fname
= synthetic_smb_fname_split(ctx
,
2029 (ucf_flags
& UCF_POSIX_PATHNAMES
));
2030 if (smb_fname
== NULL
) {
2031 return NT_STATUS_NO_MEMORY
;
2033 smb_fname
->st
= (SMB_STRUCT_STAT
) { .st_ex_nlink
= 1 };
2034 smb_fname
->st
.st_ex_btime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
2035 smb_fname
->st
.st_ex_atime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
2036 smb_fname
->st
.st_ex_mtime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
2037 smb_fname
->st
.st_ex_ctime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
2039 *_smb_fname
= smb_fname
;
2040 return NT_STATUS_OK
;
2043 status
= unix_convert(ctx
, conn
, name_in
, twrp
, &smb_fname
, ucf_flags
);
2044 if (!NT_STATUS_IS_OK(status
)) {
2045 DBG_DEBUG("unix_convert failed "
2046 "for name %s with %s\n",
2052 if ((ucf_flags
& UCF_POSIX_PATHNAMES
) &&
2053 VALID_STAT(smb_fname
->st
) &&
2054 S_ISLNK(smb_fname
->st
.st_ex_mode
))
2056 status
= check_veto_path(conn
, smb_fname
);
2057 if (!NT_STATUS_IS_OK(status
)) {
2058 TALLOC_FREE(smb_fname
);
2062 status
= check_name(conn
, smb_fname
);
2064 if (!NT_STATUS_IS_OK(status
)) {
2065 DBG_NOTICE("check_name failed "
2066 "for name %s with %s\n",
2067 smb_fname_str_dbg(smb_fname
),
2069 TALLOC_FREE(smb_fname
);
2073 if (!VALID_STAT(smb_fname
->st
)) {
2074 DBG_DEBUG("[%s] does not exist, skipping pathref fsp\n",
2075 smb_fname_str_dbg(smb_fname
));
2076 *_smb_fname
= smb_fname
;
2077 return NT_STATUS_OK
;
2080 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname
);
2081 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2083 * We deal with symlinks here as we do in
2084 * SMB_VFS_CREATE_FILE(): return success for POSIX clients with
2085 * the notable difference that there will be no fsp in
2088 * For Windows (non POSIX) clients fail with
2089 * NT_STATUS_OBJECT_NAME_NOT_FOUND.
2091 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
&&
2092 S_ISLNK(smb_fname
->st
.st_ex_mode
))
2094 status
= NT_STATUS_OK
;
2097 if (!NT_STATUS_IS_OK(status
)) {
2098 DBG_DEBUG("openat_pathref_fsp [%s] failed: %s\n",
2099 smb_fname_str_dbg(smb_fname
),
2104 *_smb_fname
= smb_fname
;
2110 * Strip a @GMT component from an SMB1-DFS path. Could be anywhere
2114 static char *strip_gmt_from_raw_dfs(TALLOC_CTX
*ctx
,
2115 const char *name_in
,
2116 bool posix_pathnames
,
2120 struct smb_filename
*smb_fname
= NULL
;
2121 char *name_out
= NULL
;
2123 smb_fname
= synthetic_smb_fname(ctx
,
2129 if (smb_fname
== NULL
) {
2132 if (!posix_pathnames
) {
2134 * Raw DFS names are still '\\' separated.
2135 * canonicalize_snapshot_path() only works
2136 * on '/' separated paths. Convert.
2138 string_replace(smb_fname
->base_name
, '\\', '/');
2140 status
= canonicalize_snapshot_path(smb_fname
,
2143 if (!NT_STATUS_IS_OK(status
)) {
2144 TALLOC_FREE(smb_fname
);
2147 if (!posix_pathnames
) {
2148 /* Replace as raw DFS names. */
2149 string_replace(smb_fname
->base_name
, '/', '\\');
2151 name_out
= talloc_strdup(ctx
, smb_fname
->base_name
);
2152 *_twrp
= smb_fname
->twrp
;
2153 TALLOC_FREE(smb_fname
);
2159 * Deal with the SMB1 semantics of sending a pathname with a
2160 * wildcard as the terminal component for a SMB1search or
2164 NTSTATUS
filename_convert_smb1_search_path(TALLOC_CTX
*ctx
,
2165 connection_struct
*conn
,
2168 struct smb_filename
**_smb_fname_out
,
2174 struct smb_filename
*smb_fname
= NULL
;
2175 bool posix_pathnames
= (ucf_flags
& UCF_POSIX_PATHNAMES
);
2178 *_smb_fname_out
= NULL
;
2181 DBG_DEBUG("name_in: %s\n", name_in
);
2183 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2184 extract_snapshot_token(name_in
, ucf_flags
, &twrp
);
2185 ucf_flags
&= ~UCF_GMT_PATHNAME
;
2188 if (ucf_flags
& UCF_DFS_PATHNAME
) {
2190 * We've been given a raw DFS pathname.
2191 * In Windows mode this is separated by '\'
2192 * characters, in POSIX by '/' characters.
2194 char path_sep
= posix_pathnames
? '/' : '\\';
2196 char *name_in_copy
= NULL
;
2197 char *last_component
= NULL
;
2199 /* Work on a copy of name_in. */
2200 name_in_copy
= talloc_strdup(ctx
, name_in
);
2201 if (name_in_copy
== NULL
) {
2202 return NT_STATUS_NO_MEMORY
;
2206 * Now we know that the last component is the
2207 * wildcard. Copy it and truncate to remove it.
2209 p
= strrchr_m(name_in_copy
, path_sep
);
2211 last_component
= talloc_strdup(ctx
, name_in_copy
);
2212 name_in_copy
[0] = '\0';
2214 last_component
= talloc_strdup(ctx
, p
+1);
2217 if (last_component
== NULL
) {
2218 return NT_STATUS_NO_MEMORY
;
2221 DBG_DEBUG("name_in_copy: %s\n", name_in_copy
);
2224 * Now we can call dfs_redirect()
2225 * on the name without wildcard.
2227 status
= dfs_redirect(ctx
,
2231 !conn
->sconn
->using_smb2
,
2234 if (!NT_STATUS_IS_OK(status
)) {
2235 DBG_DEBUG("dfs_redirect "
2236 "failed for name %s with %s\n",
2241 /* Add the last component back. */
2242 if (fname
[0] == '\0') {
2243 name_in
= talloc_strdup(ctx
, last_component
);
2245 name_in
= talloc_asprintf(ctx
,
2251 if (name_in
== NULL
) {
2252 return NT_STATUS_NO_MEMORY
;
2254 ucf_flags
&= ~UCF_DFS_PATHNAME
;
2256 DBG_DEBUG("After DFS redirect name_in: %s\n", name_in
);
2259 smb_fname
= synthetic_smb_fname(ctx
,
2265 SMB_FILENAME_POSIX_PATH
: 0);
2266 if (smb_fname
== NULL
) {
2267 return NT_STATUS_NO_MEMORY
;
2270 /* Get the original lcomp. */
2271 mask
= get_original_lcomp(ctx
,
2276 return NT_STATUS_NO_MEMORY
;
2279 if (mask
[0] == '\0') {
2280 /* Windows and OS/2 systems treat search on the root as * */
2282 mask
= talloc_strdup(ctx
, "*");
2284 return NT_STATUS_NO_MEMORY
;
2288 DBG_DEBUG("mask = %s\n", mask
);
2291 * Remove the terminal component so
2292 * filename_convert never sees the mask.
2294 p
= strrchr_m(smb_fname
->base_name
,'/');
2296 /* filename_convert handles a '\0' base_name. */
2297 smb_fname
->base_name
[0] = '\0';
2302 DBG_DEBUG("For filename_convert: smb_fname = %s\n",
2303 smb_fname_str_dbg(smb_fname
));
2305 /* Convert the parent directory path. */
2306 status
= filename_convert(ctx
,
2308 smb_fname
->base_name
,
2313 if (!NT_STATUS_IS_OK(status
)) {
2314 DBG_DEBUG("filename_convert error for %s: %s\n",
2315 smb_fname_str_dbg(smb_fname
),
2319 *_smb_fname_out
= talloc_move(ctx
, &smb_fname
);
2320 *_mask_out
= talloc_move(ctx
, &mask
);
2326 * Get the correct capitalized stream name hanging off
2327 * base_fsp. Equivalent of get_real_filename(), but for streams.
2329 static NTSTATUS
get_real_stream_name(
2330 TALLOC_CTX
*mem_ctx
,
2331 struct files_struct
*base_fsp
,
2332 const char *stream_name
,
2335 unsigned int i
, num_streams
= 0;
2336 struct stream_struct
*streams
= NULL
;
2339 status
= vfs_fstreaminfo(
2340 base_fsp
, talloc_tos(), &num_streams
, &streams
);
2341 if (!NT_STATUS_IS_OK(status
)) {
2345 for (i
=0; i
<num_streams
; i
++) {
2346 bool equal
= sname_equal(stream_name
, streams
[i
].name
, false);
2348 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
2351 equal
? "" : "not ");
2354 *_found
= talloc_move(mem_ctx
, &streams
[i
].name
);
2355 TALLOC_FREE(streams
);
2356 return NT_STATUS_OK
;
2360 TALLOC_FREE(streams
);
2361 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2364 static bool filename_split_lcomp(
2365 TALLOC_CTX
*mem_ctx
,
2366 const char *name_in
,
2369 const char **_fname_rel
,
2370 const char **_streamname
)
2372 const char *lcomp
= NULL
;
2373 const char *fname_rel
= NULL
;
2374 const char *streamname
= NULL
;
2375 char *dirname
= NULL
;
2377 if (name_in
[0] == '\0') {
2379 dirname
= talloc_strdup(mem_ctx
, "");
2380 if (dirname
== NULL
) {
2386 lcomp
= strrchr_m(name_in
, '/');
2387 if (lcomp
!= NULL
) {
2388 fname_rel
= lcomp
+1;
2389 dirname
= talloc_strndup(mem_ctx
, name_in
, lcomp
- name_in
);
2390 if (dirname
== NULL
) {
2397 * No slash, dir is emtpy
2399 dirname
= talloc_strdup(mem_ctx
, "");
2400 if (dirname
== NULL
) {
2404 if (!posix
&& (name_in
[0] == ':')) {
2406 * Special case for stream on root directory
2409 streamname
= name_in
;
2413 fname_rel
= name_in
;
2417 streamname
= strchr_m(fname_rel
, ':');
2419 if (streamname
!= NULL
) {
2420 fname_rel
= talloc_strndup(
2423 streamname
- fname_rel
);
2424 if (fname_rel
== NULL
) {
2425 TALLOC_FREE(dirname
);
2432 *_dirname
= dirname
;
2433 *_fname_rel
= fname_rel
;
2434 *_streamname
= streamname
;
2439 * Create the correct capitalization of a file name to be created.
2441 static NTSTATUS
filename_convert_normalize_new(
2442 TALLOC_CTX
*mem_ctx
,
2443 struct connection_struct
*conn
,
2447 char *name
= name_in
;
2449 *_normalized
= NULL
;
2451 if (!conn
->case_preserve
||
2452 (mangle_is_8_3(name
, false,
2454 !conn
->short_case_preserve
)) {
2456 char *normalized
= talloc_strdup(mem_ctx
, name
);
2457 if (normalized
== NULL
) {
2458 return NT_STATUS_NO_MEMORY
;
2461 strnorm(normalized
, lp_default_case(SNUM(conn
)));
2465 if (mangle_is_mangled(name
, conn
->params
)) {
2467 char *unmangled
= NULL
;
2469 found
= mangle_lookup_name_from_8_3(
2470 mem_ctx
, name
, &unmangled
, conn
->params
);
2476 if (name
!= name_in
) {
2477 *_normalized
= name
;
2480 return NT_STATUS_OK
;
2484 * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
2485 * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
2486 * the first attempt based on the filename sent by the client gives
2489 static NTSTATUS
openat_pathref_fsp_case_insensitive(
2490 struct files_struct
*dirfsp
,
2491 struct smb_filename
*smb_fname_rel
,
2494 const bool posix
= (ucf_flags
& UCF_POSIX_PATHNAMES
);
2495 DATA_BLOB cache_key
= { .data
= NULL
, };
2496 char *found_name
= NULL
;
2500 SET_STAT_INVALID(smb_fname_rel
->st
);
2502 status
= openat_pathref_fsp(dirfsp
, smb_fname_rel
);
2504 if (NT_STATUS_IS_OK(status
)) {
2505 return NT_STATUS_OK
;
2508 if (VALID_STAT(smb_fname_rel
->st
)) {
2510 * We got an error although the object existed. Might
2511 * be a symlink we don't want.
2516 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2518 * Only retry on ENOENT
2523 if (posix
|| dirfsp
->conn
->case_sensitive
) {
2525 * Only return case insensitive if required
2530 if (lp_stat_cache()) {
2531 char *base_name
= smb_fname_rel
->base_name
;
2532 DATA_BLOB value
= { .data
= NULL
};
2534 ok
= get_real_filename_cache_key(
2535 talloc_tos(), dirfsp
, base_name
, &cache_key
);
2538 * probably ENOMEM, just bail
2543 DO_PROFILE_INC(statcache_lookups
);
2545 ok
= memcache_lookup(
2546 NULL
, GETREALFILENAME_CACHE
, cache_key
, &value
);
2548 DO_PROFILE_INC(statcache_misses
);
2551 DO_PROFILE_INC(statcache_hits
);
2553 TALLOC_FREE(smb_fname_rel
->base_name
);
2554 smb_fname_rel
->base_name
= talloc_memdup(
2555 smb_fname_rel
, value
.data
, value
.length
);
2556 if (smb_fname_rel
->base_name
== NULL
) {
2557 TALLOC_FREE(cache_key
.data
);
2558 return NT_STATUS_NO_MEMORY
;
2561 status
= openat_pathref_fsp(dirfsp
, smb_fname_rel
);
2562 if (NT_STATUS_IS_OK(status
)) {
2563 TALLOC_FREE(cache_key
.data
);
2564 return NT_STATUS_OK
;
2567 memcache_delete(NULL
, GETREALFILENAME_CACHE
, cache_key
);
2571 status
= get_real_filename_at(
2572 dirfsp
, smb_fname_rel
->base_name
, smb_fname_rel
, &found_name
);
2573 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) &&
2574 (ucf_flags
& UCF_PREP_CREATEFILE
)) {
2578 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2581 if (NT_STATUS_IS_OK(status
)) {
2582 TALLOC_FREE(smb_fname_rel
->base_name
);
2583 smb_fname_rel
->base_name
= found_name
;
2585 status
= openat_pathref_fsp(dirfsp
, smb_fname_rel
);
2588 if (NT_STATUS_IS_OK(status
) && (cache_key
.data
!= NULL
)) {
2590 .data
= (uint8_t *)smb_fname_rel
->base_name
,
2591 .length
= strlen(smb_fname_rel
->base_name
) + 1,
2594 memcache_add(NULL
, GETREALFILENAME_CACHE
, cache_key
, value
);
2597 TALLOC_FREE(cache_key
.data
);
2603 * Split up name_in as sent by the client into a directory pathref fsp
2604 * and a relative smb_filename.
2606 static const char *previous_slash(const char *name_in
, const char *slash
)
2608 const char *prev
= name_in
;
2611 const char *next
= strchr_m(prev
, '/');
2613 SMB_ASSERT(next
!= NULL
); /* we have at least one slash */
2615 if (next
== slash
) {
2622 if (prev
== name_in
) {
2623 /* no previous slash */
2630 static char *symlink_target_path(
2631 TALLOC_CTX
*mem_ctx
,
2632 const char *name_in
,
2633 const char *substitute
,
2636 size_t name_in_len
= strlen(name_in
);
2637 const char *p_unparsed
= NULL
;
2638 const char *parent
= NULL
;
2641 SMB_ASSERT(unparsed
<= name_in_len
);
2643 p_unparsed
= name_in
+ (name_in_len
- unparsed
);
2645 if (substitute
[0] == '/') {
2646 ret
= talloc_asprintf(mem_ctx
, "%s%s", substitute
, p_unparsed
);
2650 if (unparsed
== 0) {
2651 parent
= strrchr_m(name_in
, '/');
2653 parent
= previous_slash(name_in
, p_unparsed
);
2656 if (parent
== NULL
) {
2657 /* no previous slash */
2661 ret
= talloc_asprintf(
2664 (int)(parent
- name_in
),
2672 * Split up name_in as sent by the client into a directory pathref fsp
2673 * and a relative smb_filename.
2675 static NTSTATUS
filename_convert_dirfsp_nosymlink(
2676 TALLOC_CTX
*mem_ctx
,
2677 connection_struct
*conn
,
2678 const char *name_in
,
2681 struct files_struct
**_dirfsp
,
2682 struct smb_filename
**_smb_fname
,
2686 struct smb_filename
*smb_dirname
= NULL
;
2687 struct smb_filename
*smb_fname_rel
= NULL
;
2688 struct smb_filename
*smb_fname
= NULL
;
2689 const bool posix
= (ucf_flags
& UCF_POSIX_PATHNAMES
);
2690 char *dirname
= NULL
;
2691 const char *fname_rel
= NULL
;
2692 const char *streamname
= NULL
;
2693 char *saved_streamname
= NULL
;
2694 struct files_struct
*base_fsp
= NULL
;
2696 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
2698 if (ucf_flags
& UCF_DFS_PATHNAME
) {
2700 NTTIME dfs_twrp
= 0;
2701 status
= dfs_redirect(
2706 !conn
->sconn
->using_smb2
,
2709 if (!NT_STATUS_IS_OK(status
)) {
2710 DBG_DEBUG("dfs_redirect "
2711 "failed for name %s with %s\n",
2717 ucf_flags
&= ~UCF_DFS_PATHNAME
;
2718 if (twrp
== 0 && dfs_twrp
!= 0) {
2723 if (is_fake_file_path(name_in
) || conn
->printer
) {
2724 smb_fname
= synthetic_smb_fname_split(mem_ctx
, name_in
, posix
);
2725 if (smb_fname
== NULL
) {
2726 return NT_STATUS_NO_MEMORY
;
2728 smb_fname
->st
= (SMB_STRUCT_STAT
) { .st_ex_nlink
= 1 };
2729 smb_fname
->st
.st_ex_btime
=
2730 (struct timespec
){0, SAMBA_UTIME_OMIT
};
2731 smb_fname
->st
.st_ex_atime
=
2732 (struct timespec
){0, SAMBA_UTIME_OMIT
};
2733 smb_fname
->st
.st_ex_mtime
=
2734 (struct timespec
){0, SAMBA_UTIME_OMIT
};
2735 smb_fname
->st
.st_ex_ctime
=
2736 (struct timespec
){0, SAMBA_UTIME_OMIT
};
2738 *_dirfsp
= conn
->cwd_fsp
;
2739 *_smb_fname
= smb_fname
;
2740 return NT_STATUS_OK
;
2744 * Catch an invalid path of "." before we
2745 * call filename_split_lcomp(). We need to
2746 * do this as filename_split_lcomp() will
2747 * use "." for the missing relative component
2748 * when an empty name_in path is sent by
2751 if (ISDOT(name_in
)) {
2752 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2756 ok
= filename_split_lcomp(
2764 status
= NT_STATUS_NO_MEMORY
;
2769 bool name_has_wild
= ms_has_wild(dirname
);
2770 name_has_wild
|= ms_has_wild(fname_rel
);
2771 if (name_has_wild
) {
2772 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2777 if (dirname
[0] == '\0') {
2778 status
= synthetic_pathref(
2785 posix
? SMB_FILENAME_POSIX_PATH
: 0,
2788 char *substitute
= NULL
;
2789 size_t unparsed
= 0;
2791 status
= openat_pathref_dirfsp_nosymlink(
2800 if (NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
2802 size_t name_in_len
= strlen(name_in
);
2803 size_t dirname_len
= strlen(dirname
);
2805 SMB_ASSERT(name_in_len
>= dirname_len
);
2807 *_substitute
= substitute
;
2808 *_unparsed
= unparsed
+ (name_in_len
- dirname_len
);
2814 if (!NT_STATUS_IS_OK(status
)) {
2815 DBG_DEBUG("opening directory %s failed: %s\n",
2818 TALLOC_FREE(dirname
);
2820 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
2822 * Except ACCESS_DENIED, everything else leads
2823 * to PATH_NOT_FOUND.
2825 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
2831 if (!VALID_STAT_OF_DIR(smb_dirname
->st
)) {
2832 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
2837 * Only look at bad last component values
2838 * once we know we have a valid directory. That
2839 * way we won't confuse error messages from
2840 * opening the directory path with error
2841 * messages from a bad last component.
2844 /* Relative filename can't be empty */
2845 if (fname_rel
[0] == '\0') {
2846 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2850 /* Relative filename can't be ".." */
2851 if (ISDOTDOT(fname_rel
)) {
2852 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2855 /* Relative name can only be dot if directory is empty. */
2856 if (ISDOT(fname_rel
) && dirname
[0] != '\0') {
2857 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2861 TALLOC_FREE(dirname
);
2863 smb_fname_rel
= synthetic_smb_fname(
2869 posix
? SMB_FILENAME_POSIX_PATH
: 0);
2870 if (smb_fname_rel
== NULL
) {
2871 status
= NT_STATUS_NO_MEMORY
;
2875 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
) &&
2876 is_named_stream(smb_fname_rel
)) {
2878 * Find the base_fsp first without the stream.
2880 saved_streamname
= smb_fname_rel
->stream_name
;
2881 smb_fname_rel
->stream_name
= NULL
;
2884 status
= normalize_filename_case(
2885 conn
, smb_fname_rel
->base_name
, ucf_flags
);
2886 if (!NT_STATUS_IS_OK(status
)) {
2887 DBG_ERR("normalize_filename_case %s failed: %s\n",
2888 smb_fname_rel
->base_name
,
2893 status
= openat_pathref_fsp_case_insensitive(
2894 smb_dirname
->fsp
, smb_fname_rel
, ucf_flags
);
2896 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2898 char *normalized
= NULL
;
2900 if (VALID_STAT(smb_fname_rel
->st
)) {
2901 #if defined(WITH_SMB1SERVER)
2903 * In SMB1 posix mode, if this is a symlink,
2904 * allow access to the name with a NULL smb_fname->fsp.
2906 if (!conn
->sconn
->using_smb2
&&
2908 S_ISLNK(smb_fname_rel
->st
.st_ex_mode
)) {
2909 SMB_ASSERT(smb_fname_rel
->fsp
== NULL
);
2910 SMB_ASSERT(streamname
== NULL
);
2912 smb_fname
= full_path_from_dirfsp_atname(
2916 if (smb_fname
== NULL
) {
2917 status
= NT_STATUS_NO_MEMORY
;
2924 * NT_STATUS_OBJECT_NAME_NOT_FOUND is
2925 * misleading: The object exists but might be
2926 * a symlink pointing outside the share.
2932 * Creating a new file
2935 status
= filename_convert_normalize_new(
2938 smb_fname_rel
->base_name
,
2940 if (!NT_STATUS_IS_OK(status
)) {
2941 DBG_DEBUG("filename_convert_normalize_new failed: "
2946 if (normalized
!= NULL
) {
2947 smb_fname_rel
->base_name
= normalized
;
2950 smb_fname_rel
->stream_name
= saved_streamname
;
2952 smb_fname
= full_path_from_dirfsp_atname(
2953 mem_ctx
, smb_dirname
->fsp
, smb_fname_rel
);
2954 if (smb_fname
== NULL
) {
2955 status
= NT_STATUS_NO_MEMORY
;
2961 if (!NT_STATUS_IS_OK(status
)) {
2965 if (saved_streamname
== NULL
) {
2966 /* smb_fname must be allocated off mem_ctx. */
2967 smb_fname
= cp_smb_filename(mem_ctx
,
2968 smb_fname_rel
->fsp
->fsp_name
);
2969 if (smb_fname
== NULL
) {
2972 status
= move_smb_fname_fsp_link(smb_fname
, smb_fname_rel
);
2973 if (!NT_STATUS_IS_OK(status
)) {
2979 base_fsp
= smb_fname_rel
->fsp
;
2980 smb_fname_fsp_unlink(smb_fname_rel
);
2981 SET_STAT_INVALID(smb_fname_rel
->st
);
2983 smb_fname_rel
->stream_name
= saved_streamname
;
2985 status
= open_stream_pathref_fsp(&base_fsp
, smb_fname_rel
);
2987 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) &&
2988 !conn
->case_sensitive
) {
2991 status
= get_real_stream_name(
2994 smb_fname_rel
->stream_name
,
2997 if (NT_STATUS_IS_OK(status
)) {
2998 smb_fname_rel
->stream_name
= found
;
3000 status
= open_stream_pathref_fsp(
3001 &base_fsp
, smb_fname_rel
);
3005 if (NT_STATUS_IS_OK(status
)) {
3006 /* smb_fname must be allocated off mem_ctx. */
3007 smb_fname
= cp_smb_filename(mem_ctx
,
3008 smb_fname_rel
->fsp
->fsp_name
);
3009 if (smb_fname
== NULL
) {
3012 status
= move_smb_fname_fsp_link(smb_fname
, smb_fname_rel
);
3013 if (!NT_STATUS_IS_OK(status
)) {
3019 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
3021 * Creating a new stream
3023 * We should save the already-open base fsp for
3024 * create_file_unixpath() somehow.
3026 smb_fname
= full_path_from_dirfsp_atname(
3027 mem_ctx
, smb_dirname
->fsp
, smb_fname_rel
);
3028 if (smb_fname
== NULL
) {
3029 status
= NT_STATUS_NO_MEMORY
;
3035 if (!NT_STATUS_IS_OK(status
)) {
3040 *_dirfsp
= smb_dirname
->fsp
;
3041 *_smb_fname
= smb_fname
;
3043 smb_fname_fsp_unlink(smb_fname_rel
);
3044 TALLOC_FREE(smb_fname_rel
);
3045 return NT_STATUS_OK
;
3048 TALLOC_FREE(dirname
);
3049 TALLOC_FREE(smb_dirname
);
3050 TALLOC_FREE(smb_fname_rel
);
3054 NTSTATUS
filename_convert_dirfsp(
3055 TALLOC_CTX
*mem_ctx
,
3056 connection_struct
*conn
,
3057 const char *name_in
,
3060 struct files_struct
**_dirfsp
,
3061 struct smb_filename
**_smb_fname
)
3063 char *substitute
= NULL
;
3064 size_t unparsed
= 0;
3066 char *target
= NULL
;
3067 char *abs_target
= NULL
;
3068 char *abs_target_canon
= NULL
;
3069 size_t symlink_redirects
= 0;
3073 if (symlink_redirects
> 40) {
3074 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3077 status
= filename_convert_dirfsp_nosymlink(
3088 #if defined(WITH_SMB1SERVER)
3090 * This isn't 100% correct, but it gets us close enough
3091 * to the old behavior for SMB1+POSIX libsmbclient. If we went through a
3092 * symlink, and we got NT_STATUS_ACCESS_DENIED on the directory
3093 * containing the target, just don't allow the client to see the
3094 * intermediate path.
3096 if (!conn
->sconn
->using_smb2
&&
3097 (ucf_flags
& UCF_POSIX_PATHNAMES
) &&
3098 symlink_redirects
> 0 &&
3099 NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
3100 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3104 if (!NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
3108 if (!lp_follow_symlinks(SNUM(conn
))) {
3109 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3113 * Right now, SMB2 and SMB1 always traverse symlinks
3114 * within the share. SMB1+POSIX traverses non-terminal
3115 * symlinks within the share.
3117 * When we add SMB2+POSIX we need to return
3118 * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
3119 * symlink target data read below if SMB2+POSIX has
3120 * UCF_POSIX_PATHNAMES set to cause the client to
3121 * resolve all symlinks locally.
3124 target
= symlink_target_path(mem_ctx
, name_in
, substitute
, unparsed
);
3125 if (target
== NULL
) {
3126 return NT_STATUS_NO_MEMORY
;
3129 DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
3135 if (target
[0] == '/') {
3136 abs_target
= target
;
3138 abs_target
= talloc_asprintf(
3139 mem_ctx
, "%s/%s", conn
->connectpath
, target
);
3140 if (abs_target
== NULL
) {
3141 return NT_STATUS_NO_MEMORY
;
3145 abs_target_canon
= canonicalize_absolute_path(mem_ctx
, abs_target
);
3146 if (abs_target_canon
== NULL
) {
3147 return NT_STATUS_NO_MEMORY
;
3150 DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon
);
3155 strlen(conn
->connectpath
)) == 0;
3157 DBG_DEBUG("wide link to %s\n", abs_target_canon
);
3158 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3161 name_in
= talloc_strdup(
3162 mem_ctx
, abs_target_canon
+ strlen(conn
->connectpath
) + 1);
3164 symlink_redirects
+= 1;
3170 * Build the full path from a dirfsp and dirfsp relative name
3172 struct smb_filename
*full_path_from_dirfsp_atname(
3173 TALLOC_CTX
*mem_ctx
,
3174 const struct files_struct
*dirfsp
,
3175 const struct smb_filename
*atname
)
3177 struct smb_filename
*fname
= NULL
;
3180 if (dirfsp
== dirfsp
->conn
->cwd_fsp
||
3181 ISDOT(dirfsp
->fsp_name
->base_name
) ||
3182 atname
->base_name
[0] == '/')
3184 path
= talloc_strdup(mem_ctx
, atname
->base_name
);
3186 path
= talloc_asprintf(mem_ctx
, "%s/%s",
3187 dirfsp
->fsp_name
->base_name
,
3194 fname
= synthetic_smb_fname(mem_ctx
,
3196 atname
->stream_name
,
3201 if (fname
== NULL
) {