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, NTTIME *twrp)
305 const char *start = NULL;
306 const char *next = NULL;
310 found = find_snapshot_token(fname, &start, &next, twrp);
315 remaining = strlen(next);
316 memmove(discard_const_p(char, start), next, remaining+1);
322 * Strip a valid @GMT-token from any incoming filename path,
323 * adding any NTTIME encoded in the pathname into the
324 * twrp field of the passed in smb_fname.
326 * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
327 * at the *start* of a pathname component.
329 * If twrp is passed in then smb_fname->twrp is set to that
330 * value, and the @GMT-token part of the filename is removed
331 * and does not change the stored smb_fname->twrp.
335 NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
342 smb_fname->twrp = twrp;
345 if (!(ucf_flags & UCF_GMT_PATHNAME)) {
349 found = extract_snapshot_token(smb_fname->base_name, &twrp);
354 if (smb_fname->twrp == 0) {
355 smb_fname->twrp = twrp;
361 static bool strnorm(char *s, int case_default)
363 if (case_default == CASE_UPPER)
364 return strupper_m(s);
366 return strlower_m(s);
370 * Utility function to normalize case on an incoming client filename
371 * if required on this connection struct.
372 * Performs an in-place case conversion guaranteed to stay the same size.
375 static NTSTATUS normalize_filename_case(connection_struct *conn,
381 if (ucf_flags & UCF_POSIX_PATHNAMES) {
383 * POSIX never normalizes filename case.
387 if (!conn->case_sensitive) {
390 if (conn->case_preserve) {
393 if (conn->short_case_preserve) {
396 ok = strnorm(filename, lp_default_case(SNUM(conn)));
398 return NT_STATUS_INVALID_PARAMETER;
403 /****************************************************************************
404 This routine is called to convert names from the dos namespace to unix
405 namespace. It needs to handle any case conversions, mangling, format changes,
408 We assume that we have already done a chdir() to the right "root" directory
411 Conversion to basic unix format is already done in check_path_syntax().
413 Names must be relative to the root of the service - any leading /. and
414 trailing /'s should have been trimmed by check_path_syntax().
416 The function will return an NTSTATUS error if some part of the name except for
417 the last part cannot be resolved, else NT_STATUS_OK.
419 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
420 didn't get any fatal errors that should immediately terminate the calling SMB
421 processing whilst resolving.
423 If the orig_path was a stream, smb_filename->base_name will point to the base
424 filename, and smb_filename->stream_name will point to the stream name. If
425 orig_path was not a stream, then smb_filename->stream_name will be NULL.
427 On exit from unix_convert, the smb_filename->st stat struct will be populated
428 if the file exists and was found, if not this stat struct will be filled with
429 zeros (and this can be detected by checking for nlinks = 0, which can never be
431 ****************************************************************************/
435 struct connection_struct *conn;
436 struct smb_filename *smb_fname;
437 const char *orig_path;
443 bool component_was_mangled;
444 bool posix_pathnames;
448 bool short_case_preserve;
451 static NTSTATUS unix_convert_step_search_fail(
452 struct uc_state *state, NTSTATUS status)
458 * An intermediate part of the name
461 DBG_DEBUG("Intermediate [%s] missing\n",
466 * We need to return the fact that the
467 * intermediate name resolution failed.
468 * This is used to return an error of
469 * ERRbadpath rather than ERRbadfile.
470 * Some Windows applications depend on
471 * the difference between these two
476 * ENOENT, ENOTDIR and ELOOP all map
477 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
478 * in the filename walk.
480 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
481 NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK) ||
482 NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
483 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
489 * ENOENT/EACCESS are the only valid errors
493 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
494 if ((state->ucf_flags & UCF_PREP_CREATEFILE) == 0) {
496 * Could be a symlink pointing to
497 * a directory outside the share
498 * to which we don't have access.
499 * If so, we need to know that here
500 * so we can return the correct error code.
501 * check_name() is never called if we
502 * error out of filename_convert().
505 struct smb_filename dname = (struct smb_filename) {
506 .base_name = state->dirpath,
507 .twrp = state->smb_fname->twrp,
510 /* handle null paths */
511 if ((dname.base_name == NULL) ||
512 (dname.base_name[0] == '\0')) {
513 return NT_STATUS_ACCESS_DENIED;
515 ret = SMB_VFS_LSTAT(state->conn, &dname);
517 return NT_STATUS_ACCESS_DENIED;
519 if (!S_ISLNK(dname.st.st_ex_mode)) {
520 return NT_STATUS_ACCESS_DENIED;
522 status = check_name(state->conn, &dname);
523 if (!NT_STATUS_IS_OK(status)) {
524 /* We know this is an intermediate path. */
525 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
527 return NT_STATUS_ACCESS_DENIED;
530 * This is the dropbox
531 * behaviour. A dropbox is a
532 * directory with only -wx
534 * get_real_filename fails
535 * with EACCESS, it needs to
536 * list the directory. We
537 * nevertheless want to allow
538 * users creating a file.
540 status = NT_STATUS_OK;
544 if (!NT_STATUS_IS_OK(status) &&
545 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
547 * ENOTDIR and ELOOP both map to
548 * NT_STATUS_OBJECT_PATH_NOT_FOUND
549 * in the filename walk.
551 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY) ||
552 NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
553 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
559 * POSIX pathnames must never call into mangling.
561 if (state->posix_pathnames) {
566 * Just the last part of the name doesn't exist.
567 * We need to strupper() or strlower() it as
568 * this conversion may be used for file creation
569 * purposes. Fix inspired by
570 * Thomas Neumann <t.neumann@iku-ag.de>.
572 if (!state->case_preserve ||
573 (mangle_is_8_3(state->name, false,
574 state->conn->params) &&
575 !state->short_case_preserve)) {
576 if (!strnorm(state->name,
577 lp_default_case(SNUM(state->conn)))) {
578 DBG_DEBUG("strnorm %s failed\n",
580 return NT_STATUS_INVALID_PARAMETER;
585 * check on the mangled stack to see if we can
586 * recover the base of the filename.
589 if (mangle_is_mangled(state->name, state->conn->params)
590 && mangle_lookup_name_from_8_3(state->mem_ctx,
593 state->conn->params)) {
596 state->name - state->smb_fname->base_name;
598 if (!ISDOT(state->dirpath)) {
599 tmp = talloc_asprintf(
600 state->smb_fname, "%s/%s",
601 state->dirpath, unmangled);
602 TALLOC_FREE(unmangled);
608 DBG_ERR("talloc failed\n");
609 return NT_STATUS_NO_MEMORY;
611 TALLOC_FREE(state->smb_fname->base_name);
612 state->smb_fname->base_name = tmp;
614 state->smb_fname->base_name + name_ofs;
615 state->end = state->name + strlen(state->name);
620 DBG_DEBUG("New file [%s]\n", state->name);
625 static NTSTATUS unix_convert_step_stat(struct uc_state *state)
627 struct smb_filename dname;
629 char *found_name = NULL;
634 * Check if the name exists up to this point.
637 DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state->smb_fname));
639 ret = vfs_stat(state->conn, state->smb_fname);
642 * It exists. it must either be a directory or this must
643 * be the last part of the path for it to be OK.
645 if (state->end && !S_ISDIR(state->smb_fname->st.st_ex_mode)) {
647 * An intermediate part of the name isn't
650 DBG_DEBUG("Not a dir [%s]\n", state->name);
653 * We need to return the fact that the
654 * intermediate name resolution failed. This
655 * is used to return an error of ERRbadpath
656 * rather than ERRbadfile. Some Windows
657 * applications depend on the difference between
660 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
665 /* Stat failed - ensure we don't use it. */
666 SET_STAT_INVALID(state->smb_fname->st);
668 if (state->posix_pathnames) {
670 * For posix_pathnames, we're done.
671 * Don't blunder into the
672 * get_real_filename() codepath as they may
673 * be doing case insensitive lookups. So when
674 * creating a new POSIX directory Foo they might
677 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
679 if (state->end != NULL) {
680 const char *morepath = NULL;
682 * If this is intermediate we must
683 * restore the full path.
687 * If there are any more components
688 * after the failed LSTAT we cannot
691 morepath = strchr(state->end + 1, '/');
692 if (morepath != NULL) {
693 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
696 if (errno == ENOENT) {
697 /* New file or directory. */
701 if ((errno == EACCES) &&
702 (state->ucf_flags & UCF_PREP_CREATEFILE)) {
703 /* POSIX Dropbox case. */
708 return map_nt_error_from_unix(errno);
712 * Reset errno so we can detect
713 * directory open errors.
718 * Try to find this part of the path in the directory.
721 dname = (struct smb_filename) {
722 .base_name = state->dirpath,
723 .twrp = state->smb_fname->twrp,
726 /* handle null paths */
727 if ((dname.base_name == NULL) || (dname.base_name[0] == '\0')) {
728 dname.base_name = dot;
731 status = get_real_filename(state->conn,
736 if (!NT_STATUS_IS_OK(status)) {
737 return unix_convert_step_search_fail(state, status);
741 * Restore the rest of the string. If the string was
742 * mangled the size may have changed.
747 state->name - state->smb_fname->base_name;
749 if (!ISDOT(state->dirpath)) {
750 tmp = talloc_asprintf(state->smb_fname,
751 "%s/%s/%s", state->dirpath,
752 found_name, state->end+1);
755 tmp = talloc_asprintf(state->smb_fname,
760 DBG_ERR("talloc_asprintf failed\n");
761 return NT_STATUS_NO_MEMORY;
763 TALLOC_FREE(state->smb_fname->base_name);
764 state->smb_fname->base_name = tmp;
765 state->name = state->smb_fname->base_name + name_ofs;
766 state->end = state->name + strlen(found_name);
771 state->name - state->smb_fname->base_name;
773 if (!ISDOT(state->dirpath)) {
774 tmp = talloc_asprintf(state->smb_fname,
775 "%s/%s", state->dirpath,
778 tmp = talloc_strdup(state->smb_fname,
782 DBG_ERR("talloc failed\n");
783 return NT_STATUS_NO_MEMORY;
785 TALLOC_FREE(state->smb_fname->base_name);
786 state->smb_fname->base_name = tmp;
787 state->name = state->smb_fname->base_name + name_ofs;
790 * We just scanned for, and found the end of
791 * the path. We must return a valid stat struct
795 ret = vfs_stat(state->conn, state->smb_fname);
797 SET_STAT_INVALID(state->smb_fname->st);
801 TALLOC_FREE(found_name);
805 static NTSTATUS unix_convert_step(struct uc_state *state)
810 * Pinpoint the end of this section of the filename.
812 /* mb safe. '/' can't be in any encoded char. */
813 state->end = strchr(state->name, '/');
816 * Chop the name at this point.
818 if (state->end != NULL) {
822 DBG_DEBUG("dirpath [%s] name [%s]\n", state->dirpath, state->name);
824 /* The name cannot have a component of "." */
826 if (ISDOT(state->name)) {
827 if (state->end == NULL) {
828 /* Error code at the end of a pathname. */
829 return NT_STATUS_OBJECT_NAME_INVALID;
831 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
834 status = unix_convert_step_stat(state);
835 if (!NT_STATUS_IS_OK(status)) {
843 * Add to the dirpath that we have resolved so far.
846 if (!ISDOT(state->dirpath)) {
847 char *tmp = talloc_asprintf(state->mem_ctx,
848 "%s/%s", state->dirpath, state->name);
850 DBG_ERR("talloc_asprintf failed\n");
851 return NT_STATUS_NO_MEMORY;
853 TALLOC_FREE(state->dirpath);
854 state->dirpath = tmp;
857 TALLOC_FREE(state->dirpath);
858 if (!(state->dirpath = talloc_strdup(state->mem_ctx,state->name))) {
859 DBG_ERR("talloc_strdup failed\n");
860 return NT_STATUS_NO_MEMORY;
865 * Cache the dirpath thus far. Don't cache a name with mangled
866 * components as this can change the size.
868 if(!state->component_was_mangled) {
869 stat_cache_add(state->orig_path,
871 state->smb_fname->twrp,
872 state->case_sensitive);
876 * Restore the / that we wiped out earlier.
878 if (state->end != NULL) {
885 NTSTATUS unix_convert(TALLOC_CTX *mem_ctx,
886 connection_struct *conn,
887 const char *orig_path,
889 struct smb_filename **smb_fname_out,
892 struct uc_state uc_state;
893 struct uc_state *state = &uc_state;
896 int parent_stat_errno = 0;
898 *state = (struct uc_state) {
901 .orig_path = orig_path,
902 .ucf_flags = ucf_flags,
903 .posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES),
904 .case_sensitive = conn->case_sensitive,
905 .case_preserve = conn->case_preserve,
906 .short_case_preserve = conn->short_case_preserve,
909 *smb_fname_out = NULL;
911 if (state->posix_pathnames) {
912 /* POSIX means ignore case settings on share. */
913 state->case_sensitive = true;
914 state->case_preserve = true;
915 state->short_case_preserve = true;
918 state->smb_fname = talloc_zero(state->mem_ctx, struct smb_filename);
919 if (state->smb_fname == NULL) {
920 return NT_STATUS_NO_MEMORY;
923 if (state->conn->printer) {
924 /* we don't ever use the filenames on a printer share as a
925 filename - so don't convert them */
926 state->smb_fname->base_name = talloc_strdup(
927 state->smb_fname, state->orig_path);
928 if (state->smb_fname->base_name == NULL) {
929 status = NT_STATUS_NO_MEMORY;
935 state->smb_fname->flags = state->posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0;
937 DBG_DEBUG("Called on file [%s]\n", state->orig_path);
939 if (state->orig_path[0] == '/') {
940 DBG_ERR("Path [%s] starts with '/'\n", state->orig_path);
941 return NT_STATUS_OBJECT_NAME_INVALID;
944 /* Start with the full orig_path as given by the caller. */
945 state->smb_fname->base_name = talloc_strdup(
946 state->smb_fname, state->orig_path);
947 if (state->smb_fname->base_name == NULL) {
948 DBG_ERR("talloc_strdup failed\n");
949 status = NT_STATUS_NO_MEMORY;
953 /* Canonicalize any @GMT- paths. */
954 status = canonicalize_snapshot_path(state->smb_fname, ucf_flags, twrp);
955 if (!NT_STATUS_IS_OK(status)) {
960 * If we trimmed down to a single '\0' character
961 * then we should use the "." directory to avoid
962 * searching the cache, but not if we are in a
964 * As we know this is valid we can return true here.
967 if (state->smb_fname->base_name[0] == '\0') {
968 state->smb_fname->base_name = talloc_strdup(state->smb_fname, ".");
969 if (state->smb_fname->base_name == NULL) {
970 status = NT_STATUS_NO_MEMORY;
973 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
974 status = map_nt_error_from_unix(errno);
977 DBG_DEBUG("conversion finished [] -> [%s]\n",
978 state->smb_fname->base_name);
982 if (state->orig_path[0] == '.' && (state->orig_path[1] == '/' ||
983 state->orig_path[1] == '\0')) {
984 /* Start of pathname can't be "." only. */
985 if (state->orig_path[1] == '\0' || state->orig_path[2] == '\0') {
986 status = NT_STATUS_OBJECT_NAME_INVALID;
988 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
994 * Large directory fix normalization. If we're case sensitive, and
995 * the case preserving parameters are set to "no", normalize the case of
996 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
997 * This is in conflict with the current (3.0.20) man page, but is
998 * what people expect from the "large directory howto". I'll update
999 * the man page. Thanks to jht@samba.org for finding this. JRA.
1002 status = normalize_filename_case(state->conn,
1003 state->smb_fname->base_name,
1005 if (!NT_STATUS_IS_OK(status)) {
1006 DBG_ERR("normalize_filename_case %s failed\n",
1007 state->smb_fname->base_name);
1012 * Strip off the stream, and add it back when we're done with the
1015 if (!state->posix_pathnames) {
1016 state->stream = strchr_m(state->smb_fname->base_name, ':');
1018 if (state->stream != NULL) {
1019 char *tmp = talloc_strdup(state->smb_fname, state->stream);
1021 status = NT_STATUS_NO_MEMORY;
1025 * Since this is actually pointing into
1026 * smb_fname->base_name this truncates base_name.
1028 *state->stream = '\0';
1029 state->stream = tmp;
1031 if (state->smb_fname->base_name[0] == '\0') {
1033 * orig_name was just a stream name.
1034 * This is a stream on the root of
1035 * the share. Replace base_name with
1038 state->smb_fname->base_name =
1039 talloc_strdup(state->smb_fname, ".");
1040 if (state->smb_fname->base_name == NULL) {
1041 status = NT_STATUS_NO_MEMORY;
1044 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
1045 status = map_nt_error_from_unix(errno);
1048 /* dirpath must exist. */
1049 state->dirpath = talloc_strdup(state->mem_ctx,".");
1050 if (state->dirpath == NULL) {
1051 status = NT_STATUS_NO_MEMORY;
1054 DBG_INFO("conversion finished [%s] -> [%s]\n",
1056 state->smb_fname->base_name);
1062 state->name = state->smb_fname->base_name;
1065 * If we're providing case insensitive semantics or
1066 * the underlying filesystem is case insensitive,
1067 * then a case-normalized hit in the stat-cache is
1068 * authoritative. JRA.
1070 * Note: We're only checking base_name. The stream_name will be
1071 * added and verified in build_stream_path().
1074 if (!state->case_sensitive ||
1075 !(state->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
1079 found = stat_cache_lookup(state->conn,
1080 &state->smb_fname->base_name,
1083 state->smb_fname->twrp,
1084 &state->smb_fname->st);
1086 * stat_cache_lookup() allocates on talloc_tos() even
1087 * when !found, reparent correctly
1089 talloc_steal(state->smb_fname, state->smb_fname->base_name);
1090 talloc_steal(state->mem_ctx, state->dirpath);
1098 * Make sure "dirpath" is an allocated string, we use this for
1099 * building the directories with talloc_asprintf and free it.
1102 if (state->dirpath == NULL) {
1103 state->dirpath = talloc_strdup(state->mem_ctx,".");
1104 if (state->dirpath == NULL) {
1105 DBG_ERR("talloc_strdup failed\n");
1106 status = NT_STATUS_NO_MEMORY;
1112 * If we have a wildcard we must walk the path to
1113 * find where the error is, even if case sensitive
1117 if (!state->posix_pathnames) {
1118 /* POSIX pathnames have no wildcards. */
1119 bool name_has_wildcard = ms_has_wild(state->smb_fname->base_name);
1120 if (name_has_wildcard) {
1121 /* Wildcard not valid anywhere. */
1122 status = NT_STATUS_OBJECT_NAME_INVALID;
1127 DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
1128 state->smb_fname->base_name, state->dirpath, state->name);
1131 * stat the name - if it exists then we can add the stream back (if
1132 * there was one) and be done!
1135 ret = vfs_stat(state->conn, state->smb_fname);
1137 status = check_for_dot_component(state->smb_fname);
1138 if (!NT_STATUS_IS_OK(status)) {
1141 /* Add the path (not including the stream) to the cache. */
1142 stat_cache_add(state->orig_path,
1143 state->smb_fname->base_name,
1144 state->smb_fname->twrp,
1145 state->case_sensitive);
1146 DBG_DEBUG("Conversion of base_name finished "
1148 state->orig_path, state->smb_fname->base_name);
1152 /* Stat failed - ensure we don't use it. */
1153 SET_STAT_INVALID(state->smb_fname->st);
1156 * Note: we must continue processing a path if we get EACCES
1157 * from stat. With NFS4 permissions the file might be lacking
1158 * READ_ATTR, but if the parent has LIST permissions we can
1159 * resolve the path in the path traversal loop down below.
1162 if (errno == ENOENT) {
1163 /* Optimization when creating a new file - only
1164 the last component doesn't exist.
1165 NOTE : check_parent_exists() doesn't preserve errno.
1167 int saved_errno = errno;
1168 status = check_parent_exists(state->mem_ctx,
1170 state->posix_pathnames,
1174 &parent_stat_errno);
1175 errno = saved_errno;
1176 if (!NT_STATUS_IS_OK(status)) {
1182 * A special case - if we don't have any wildcards or mangling chars and are case
1183 * sensitive or the underlying filesystem is case insensitive then searching
1186 * NB. As POSIX sets state->case_sensitive as
1187 * true we will never call into mangle_is_mangled() here.
1190 if ((state->case_sensitive || !(state->conn->fs_capabilities &
1191 FILE_CASE_SENSITIVE_SEARCH)) &&
1192 !mangle_is_mangled(state->smb_fname->base_name, state->conn->params)) {
1194 status = check_for_dot_component(state->smb_fname);
1195 if (!NT_STATUS_IS_OK(status)) {
1200 * The stat failed. Could be ok as it could be
1204 if (errno == ENOTDIR || errno == ELOOP) {
1205 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1207 } else if (errno == ENOENT) {
1209 * Was it a missing last component ?
1210 * or a missing intermediate component ?
1214 * For this code path we can guarantee that
1215 * we have gone through check_parent_exists()
1216 * and it returned NT_STATUS_OK.
1218 * Either there was no parent component (".")
1219 * parent_stat_errno == 0 and we have a missing
1220 * last component here.
1222 * OR check_parent_exists() called STAT/LSTAT
1223 * and if it failed parent_stat_errno has been
1224 * set telling us if the parent existed or not.
1226 * Either way we can avoid another STAT/LSTAT
1227 * system call on the parent here.
1229 if (parent_stat_errno == ENOTDIR ||
1230 parent_stat_errno == ENOENT ||
1231 parent_stat_errno == ELOOP) {
1232 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1237 * Missing last component is ok - new file.
1238 * Also deal with permission denied elsewhere.
1239 * Just drop out to done.
1246 * is_mangled() was changed to look at an entire pathname, not
1247 * just a component. JRA.
1250 if (state->posix_pathnames) {
1252 * POSIX names are never mangled and we must not
1253 * call into mangling functions.
1255 state->component_was_mangled = false;
1256 } else if (mangle_is_mangled(state->name, state->conn->params)) {
1257 state->component_was_mangled = true;
1261 * Now we need to recursively match the name against the real
1262 * directory structure.
1266 * Match each part of the path name separately, trying the names
1267 * as is first, then trying to scan the directory for matching names.
1270 for (; state->name ; state->name = (state->end ? state->end + 1:(char *)NULL)) {
1271 status = unix_convert_step(state);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1284 * Cache the full path. Don't cache a name with mangled or wildcard
1285 * components as this can change the size.
1288 if(!state->component_was_mangled) {
1289 stat_cache_add(state->orig_path,
1290 state->smb_fname->base_name,
1291 state->smb_fname->twrp,
1292 state->case_sensitive);
1296 * The name has been resolved.
1300 /* Add back the stream if one was stripped off originally. */
1301 if (state->stream != NULL) {
1302 state->smb_fname->stream_name = state->stream;
1304 /* Check path now that the base_name has been converted. */
1305 status = build_stream_path(state->mem_ctx, state->conn, state->smb_fname);
1306 if (!NT_STATUS_IS_OK(status)) {
1311 DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
1312 state->orig_path, smb_fname_str_dbg(state->smb_fname));
1314 TALLOC_FREE(state->dirpath);
1315 *smb_fname_out = state->smb_fname;
1316 return NT_STATUS_OK;
1318 DBG_DEBUG("Conversion failed: dirpath [%s] name [%s]\n",
1319 state->dirpath, state->name);
1320 if ((state->dirpath != NULL) && !ISDOT(state->dirpath)) {
1321 state->smb_fname->base_name = talloc_asprintf(
1327 state->smb_fname->base_name = talloc_strdup(
1328 state->smb_fname, state->name);
1330 if (state->smb_fname->base_name == NULL) {
1331 DBG_ERR("talloc_asprintf failed\n");
1332 status = NT_STATUS_NO_MEMORY;
1336 *smb_fname_out = state->smb_fname;
1337 TALLOC_FREE(state->dirpath);
1340 TALLOC_FREE(state->smb_fname);
1344 /****************************************************************************
1345 Ensure a path is not vetoed.
1346 ****************************************************************************/
1348 static NTSTATUS check_veto_path(connection_struct *conn,
1349 const struct smb_filename *smb_fname)
1351 const char *name = smb_fname->base_name;
1353 if (IS_VETO_PATH(conn, name)) {
1354 /* Is it not dot or dot dot. */
1355 if (!(ISDOT(name) || ISDOTDOT(name))) {
1356 DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1358 return map_nt_error_from_unix(ENOENT);
1361 return NT_STATUS_OK;
1364 /****************************************************************************
1365 Check a filename - possibly calling check_reduced_name.
1366 This is called by every routine before it allows an operation on a filename.
1367 It does any final confirmation necessary to ensure that the filename is
1368 a valid one for the user to access.
1369 ****************************************************************************/
1371 static NTSTATUS check_name(connection_struct *conn,
1372 const struct smb_filename *smb_fname)
1374 NTSTATUS status = check_veto_path(conn, smb_fname);
1376 if (!NT_STATUS_IS_OK(status)) {
1380 if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
1381 status = check_reduced_name(conn, NULL, smb_fname);
1382 if (!NT_STATUS_IS_OK(status)) {
1383 DEBUG(5,("check_name: name %s failed with %s\n",
1384 smb_fname->base_name,
1385 nt_errstr(status)));
1390 return NT_STATUS_OK;
1393 /****************************************************************************
1394 Check if two filenames are equal.
1395 This needs to be careful about whether we are case sensitive.
1396 ****************************************************************************/
1398 static bool fname_equal(const char *name1, const char *name2,
1399 bool case_sensitive)
1401 /* Normal filename handling */
1402 if (case_sensitive) {
1403 return(strcmp(name1,name2) == 0);
1406 return(strequal(name1,name2));
1409 static bool sname_equal(const char *name1, const char *name2,
1410 bool case_sensitive)
1413 const char *s1 = NULL;
1414 const char *s2 = NULL;
1417 const char *e1 = NULL;
1418 const char *e2 = NULL;
1422 match = fname_equal(name1, name2, case_sensitive);
1427 if (name1[0] != ':') {
1430 if (name2[0] != ':') {
1434 e1 = strchr(s1, ':');
1438 n1 = PTR_DIFF(e1, s1);
1441 e2 = strchr(s2, ':');
1445 n2 = PTR_DIFF(e2, s2);
1448 /* Normal filename handling */
1449 if (case_sensitive) {
1450 return (strncmp(s1, s2, n1) == 0);
1454 * We can't use strnequal() here
1455 * as it takes the number of codepoints
1456 * and not the number of bytes.
1458 * So we make a copy before calling
1461 * Note that we TALLOC_FREE() in reverse order
1462 * in order to avoid memory fragmentation.
1465 c1 = talloc_strndup(talloc_tos(), s1, n1);
1466 c2 = talloc_strndup(talloc_tos(), s2, n2);
1467 if (c1 == NULL || c2 == NULL) {
1470 return (strncmp(s1, s2, n1) == 0);
1473 match = strequal(c1, c2);
1479 /****************************************************************************
1480 Scan a directory to find a filename, matching without case sensitivity.
1481 If the name looks like a mangled name then try via the mangling functions
1482 ****************************************************************************/
1484 NTSTATUS get_real_filename_full_scan_at(struct files_struct *dirfsp,
1487 TALLOC_CTX *mem_ctx,
1490 struct connection_struct *conn = dirfsp->conn;
1491 struct smb_Dir *cur_dir = NULL;
1492 const char *dname = NULL;
1493 char *talloced = NULL;
1494 char *unmangled_name = NULL;
1498 /* If we have a case-sensitive filesystem, it doesn't do us any
1499 * good to search for a name. If a case variation of the name was
1500 * there, then the original stat(2) would have found it.
1502 if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
1503 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1507 * The incoming name can be mangled, and if we de-mangle it
1508 * here it will not compare correctly against the filename (name2)
1509 * read from the directory and then mangled by the name_to_8_3()
1510 * call. We need to mangle both names or neither.
1513 * Fix for bug found by Dina Fine. If in case sensitive mode then
1514 * the mangle cache is no good (3 letter extension could be wrong
1515 * case - so don't demangle in this case - leave as mangled and
1516 * allow the mangling of the directory entry read (which is done
1517 * case insensitively) to match instead. This will lead to more
1518 * false positive matches but we fail completely without it. JRA.
1521 if (mangled && !conn->case_sensitive) {
1522 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
1526 /* Name is now unmangled. */
1527 name = unmangled_name;
1531 /* open the directory */
1532 status = OpenDir_from_pathref(talloc_tos(), dirfsp, NULL, 0, &cur_dir);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 DBG_NOTICE("scan dir didn't open dir [%s]: %s\n",
1535 fsp_str_dbg(dirfsp),
1537 TALLOC_FREE(unmangled_name);
1541 /* now scan for matching names */
1543 while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
1545 /* Is it dot or dot dot. */
1546 if (ISDOT(dname) || ISDOTDOT(dname)) {
1547 TALLOC_FREE(talloced);
1552 * At this point dname is the unmangled name.
1553 * name is either mangled or not, depending on the state
1554 * of the "mangled" variable. JRA.
1558 * Check mangled name against mangled name, or unmangled name
1559 * against unmangled name.
1562 if ((mangled && mangled_equal(name,dname,conn->params)) ||
1563 fname_equal(name, dname, conn->case_sensitive)) {
1564 /* we've found the file, change it's name and return */
1565 *found_name = talloc_strdup(mem_ctx, dname);
1566 TALLOC_FREE(unmangled_name);
1567 TALLOC_FREE(cur_dir);
1569 TALLOC_FREE(talloced);
1570 return NT_STATUS_NO_MEMORY;
1572 TALLOC_FREE(talloced);
1573 return NT_STATUS_OK;
1575 TALLOC_FREE(talloced);
1578 TALLOC_FREE(unmangled_name);
1579 TALLOC_FREE(cur_dir);
1580 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1583 NTSTATUS get_real_filename_full_scan(connection_struct *conn,
1587 TALLOC_CTX *mem_ctx,
1590 struct smb_filename *smb_dname = NULL;
1593 /* handle null paths */
1594 if ((path == NULL) || (*path == 0)) {
1598 status = synthetic_pathref(
1607 if (!NT_STATUS_IS_OK(status)) {
1611 status = get_real_filename_full_scan_at(
1612 smb_dname->fsp, name, mangled, mem_ctx, found_name);
1614 TALLOC_FREE(smb_dname);
1618 /****************************************************************************
1619 Wrapper around the vfs get_real_filename and the full directory scan
1621 ****************************************************************************/
1623 NTSTATUS get_real_filename_at(struct files_struct *dirfsp,
1625 TALLOC_CTX *mem_ctx,
1628 struct connection_struct *conn = dirfsp->conn;
1632 mangled = mangle_is_mangled(name, conn->params);
1635 status = get_real_filename_full_scan_at(
1636 dirfsp, name, mangled, mem_ctx, found_name);
1640 /* Try the vfs first to take advantage of case-insensitive stat. */
1641 status = SMB_VFS_GET_REAL_FILENAME_AT(
1642 dirfsp->conn, dirfsp, name, mem_ctx, found_name);
1645 * If the case-insensitive stat was successful, or returned an error
1646 * other than EOPNOTSUPP then there is no need to fall back on the
1647 * full directory scan.
1649 if (NT_STATUS_IS_OK(status) ||
1650 !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1654 status = get_real_filename_full_scan_at(
1655 dirfsp, name, mangled, mem_ctx, found_name);
1660 * Create the memcache-key for GETREALFILENAME_CACHE: This supplements
1661 * the stat cache for the last component to be looked up. Cache
1662 * contents is the correctly capitalized translation of the parameter
1663 * "name" as it exists on disk. This is indexed by inode of the dirfsp
1664 * and name, and contrary to stat_cahce_lookup() it does not
1665 * vfs_stat() the last component. This will be taken care of by an
1666 * attempt to do a openat_pathref_fsp().
1668 static bool get_real_filename_cache_key(
1669 TALLOC_CTX *mem_ctx,
1670 struct files_struct *dirfsp,
1674 struct file_id fid = vfs_file_id_from_sbuf(
1675 dirfsp->conn, &dirfsp->fsp_name->st);
1677 uint8_t *key = NULL;
1678 size_t namelen, keylen;
1680 upper = talloc_strdup_upper(mem_ctx, name);
1681 if (upper == NULL) {
1684 namelen = talloc_get_size(upper);
1686 keylen = namelen + sizeof(fid);
1687 if (keylen < sizeof(fid)) {
1692 key = talloc_size(mem_ctx, keylen);
1698 memcpy(key, &fid, sizeof(fid));
1699 memcpy(key + sizeof(fid), upper, namelen);
1702 *_key = (DATA_BLOB) { .data = key, .length = keylen, };
1706 static NTSTATUS get_real_filename(connection_struct *conn,
1707 struct smb_filename *path,
1709 TALLOC_CTX *mem_ctx,
1712 struct smb_filename *smb_dname = NULL;
1715 smb_dname = cp_smb_filename_nostream(talloc_tos(), path);
1716 if (smb_dname == NULL) {
1717 return NT_STATUS_NO_MEMORY;
1721 status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
1723 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
1724 S_ISLNK(smb_dname->st.st_ex_mode)) {
1725 status = NT_STATUS_STOPPED_ON_SYMLINK;
1728 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
1729 (smb_dname->twrp != 0)) {
1731 * Retry looking at the non-snapshot path, copying the
1732 * fallback mechanism from vfs_shadow_copy2.c when
1733 * shadow_copy2_convert() fails. This path-based
1734 * routine get_real_filename() should go away and be
1735 * replaced with a fd-based one, so spoiling it with a
1736 * shadow_copy2 specific mechanism should not be too
1739 smb_dname->twrp = 0;
1743 if (!NT_STATUS_IS_OK(status)) {
1744 DBG_DEBUG("openat_pathref_fsp(%s) failed: %s\n",
1745 smb_fname_str_dbg(smb_dname),
1749 * ENOTDIR and ELOOP both map to
1750 * NT_STATUS_OBJECT_PATH_NOT_FOUND in the filename
1753 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY) ||
1754 NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
1755 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1761 status = get_real_filename_at(
1762 smb_dname->fsp, name, mem_ctx, found_name);
1763 TALLOC_FREE(smb_dname);
1767 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1768 connection_struct *conn,
1769 struct smb_filename *smb_fname)
1772 unsigned int i, num_streams = 0;
1773 struct stream_struct *streams = NULL;
1774 struct smb_filename *pathref = NULL;
1776 if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1777 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1778 return NT_STATUS_OK;
1781 if (errno != ENOENT) {
1782 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1783 status = map_nt_error_from_unix(errno);
1787 if (smb_fname->fsp == NULL) {
1788 status = synthetic_pathref(mem_ctx,
1790 smb_fname->base_name,
1796 if (!NT_STATUS_IS_OK(status)) {
1797 if (NT_STATUS_EQUAL(status,
1798 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1799 TALLOC_FREE(pathref);
1800 SET_STAT_INVALID(smb_fname->st);
1801 return NT_STATUS_OK;
1803 DBG_DEBUG("synthetic_pathref failed: %s\n",
1808 pathref = smb_fname;
1811 /* Fall back to a case-insensitive scan of all streams on the file. */
1812 status = vfs_fstreaminfo(pathref->fsp, mem_ctx,
1813 &num_streams, &streams);
1814 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1815 SET_STAT_INVALID(smb_fname->st);
1816 TALLOC_FREE(pathref);
1817 return NT_STATUS_OK;
1820 if (!NT_STATUS_IS_OK(status)) {
1821 DEBUG(10, ("vfs_fstreaminfo failed: %s\n", nt_errstr(status)));
1825 for (i=0; i<num_streams; i++) {
1826 bool equal = sname_equal(
1827 smb_fname->stream_name,
1829 conn->case_sensitive);
1831 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
1832 smb_fname->stream_name,
1834 equal ? "" : "not ");
1841 /* Couldn't find the stream. */
1842 if (i == num_streams) {
1843 SET_STAT_INVALID(smb_fname->st);
1844 TALLOC_FREE(pathref);
1845 TALLOC_FREE(streams);
1846 return NT_STATUS_OK;
1849 DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1850 smb_fname->stream_name, streams[i].name));
1853 TALLOC_FREE(smb_fname->stream_name);
1854 smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
1855 if (smb_fname->stream_name == NULL) {
1856 status = NT_STATUS_NO_MEMORY;
1860 SET_STAT_INVALID(smb_fname->st);
1862 if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1863 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1865 status = NT_STATUS_OK;
1867 TALLOC_FREE(pathref);
1868 TALLOC_FREE(streams);
1873 * Lightweight function to just get last component
1874 * for rename / enumerate directory calls.
1877 char *get_original_lcomp(TALLOC_CTX *ctx,
1878 connection_struct *conn,
1879 const char *filename_in,
1882 char *last_slash = NULL;
1886 last_slash = strrchr(filename_in, '/');
1887 if (last_slash != NULL) {
1888 orig_lcomp = talloc_strdup(ctx, last_slash+1);
1890 orig_lcomp = talloc_strdup(ctx, filename_in);
1892 if (orig_lcomp == NULL) {
1895 status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 TALLOC_FREE(orig_lcomp);
1904 * Deal with the SMB1 semantics of sending a pathname with a
1905 * wildcard as the terminal component for a SMB1search or
1909 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
1910 connection_struct *conn,
1913 struct files_struct **_dirfsp,
1914 struct smb_filename **_smb_fname_out,
1920 struct smb_filename *smb_fname = NULL;
1923 *_smb_fname_out = NULL;
1927 DBG_DEBUG("name_in: %s\n", name_in);
1929 if (ucf_flags & UCF_GMT_PATHNAME) {
1930 extract_snapshot_token(name_in, &twrp);
1931 ucf_flags &= ~UCF_GMT_PATHNAME;
1934 if (ucf_flags & UCF_DFS_PATHNAME) {
1936 * We've been given a raw DFS pathname.
1938 char *pathname = NULL;
1939 DBG_DEBUG("Before dfs_filename_convert name_in: %s\n", name_in);
1940 status = dfs_filename_convert(ctx,
1945 if (!NT_STATUS_IS_OK(status)) {
1946 DBG_DEBUG("dfs_filename_convert "
1947 "failed for name %s with %s\n",
1952 ucf_flags &= ~UCF_DFS_PATHNAME;
1954 DBG_DEBUG("After dfs_filename_convert name_in: %s\n", name_in);
1957 /* Get the original lcomp. */
1958 mask = get_original_lcomp(ctx,
1963 return NT_STATUS_NO_MEMORY;
1966 if (mask[0] == '\0') {
1967 /* Windows and OS/2 systems treat search on the root as * */
1969 mask = talloc_strdup(ctx, "*");
1971 return NT_STATUS_NO_MEMORY;
1975 DBG_DEBUG("mask = %s\n", mask);
1978 * Remove the terminal component so
1979 * filename_convert_dirfsp never sees the mask.
1981 p = strrchr_m(name_in,'/');
1983 /* filename_convert_dirfsp handles a '\0' name. */
1989 DBG_DEBUG("For filename_convert_dirfsp: name_in = %s\n",
1992 /* Convert the parent directory path. */
1993 status = filename_convert_dirfsp(ctx,
2001 if (!NT_STATUS_IS_OK(status)) {
2002 DBG_DEBUG("filename_convert error for %s: %s\n",
2007 *_smb_fname_out = talloc_move(ctx, &smb_fname);
2008 *_mask_out = talloc_move(ctx, &mask);
2014 * Get the correct capitalized stream name hanging off
2015 * base_fsp. Equivalent of get_real_filename(), but for streams.
2017 static NTSTATUS get_real_stream_name(
2018 TALLOC_CTX *mem_ctx,
2019 struct files_struct *base_fsp,
2020 const char *stream_name,
2023 unsigned int i, num_streams = 0;
2024 struct stream_struct *streams = NULL;
2027 status = vfs_fstreaminfo(
2028 base_fsp, talloc_tos(), &num_streams, &streams);
2029 if (!NT_STATUS_IS_OK(status)) {
2033 for (i=0; i<num_streams; i++) {
2034 bool equal = sname_equal(stream_name, streams[i].name, false);
2036 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
2039 equal ? "" : "not ");
2042 *_found = talloc_move(mem_ctx, &streams[i].name);
2043 TALLOC_FREE(streams);
2044 return NT_STATUS_OK;
2048 TALLOC_FREE(streams);
2049 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2052 static bool filename_split_lcomp(
2053 TALLOC_CTX *mem_ctx,
2054 const char *name_in,
2057 const char **_fname_rel,
2058 const char **_streamname)
2060 const char *lcomp = NULL;
2061 const char *fname_rel = NULL;
2062 const char *streamname = NULL;
2063 char *dirname = NULL;
2065 if (name_in[0] == '\0') {
2067 dirname = talloc_strdup(mem_ctx, "");
2068 if (dirname == NULL) {
2074 lcomp = strrchr_m(name_in, '/');
2075 if (lcomp != NULL) {
2076 fname_rel = lcomp+1;
2077 dirname = talloc_strndup(mem_ctx, name_in, lcomp - name_in);
2078 if (dirname == NULL) {
2085 * No slash, dir is emtpy
2087 dirname = talloc_strdup(mem_ctx, "");
2088 if (dirname == NULL) {
2092 if (!posix && (name_in[0] == ':')) {
2094 * Special case for stream on root directory
2097 streamname = name_in;
2101 fname_rel = name_in;
2105 streamname = strchr_m(fname_rel, ':');
2107 if (streamname != NULL) {
2108 fname_rel = talloc_strndup(
2111 streamname - fname_rel);
2112 if (fname_rel == NULL) {
2113 TALLOC_FREE(dirname);
2120 *_dirname = dirname;
2121 *_fname_rel = fname_rel;
2122 *_streamname = streamname;
2127 * Create the correct capitalization of a file name to be created.
2129 static NTSTATUS filename_convert_normalize_new(
2130 TALLOC_CTX *mem_ctx,
2131 struct connection_struct *conn,
2135 char *name = name_in;
2137 *_normalized = NULL;
2139 if (!conn->case_preserve ||
2140 (mangle_is_8_3(name, false,
2142 !conn->short_case_preserve)) {
2144 char *normalized = talloc_strdup(mem_ctx, name);
2145 if (normalized == NULL) {
2146 return NT_STATUS_NO_MEMORY;
2149 strnorm(normalized, lp_default_case(SNUM(conn)));
2153 if (mangle_is_mangled(name, conn->params)) {
2155 char *unmangled = NULL;
2157 found = mangle_lookup_name_from_8_3(
2158 mem_ctx, name, &unmangled, conn->params);
2164 if (name != name_in) {
2165 *_normalized = name;
2168 return NT_STATUS_OK;
2172 * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
2173 * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
2174 * the first attempt based on the filename sent by the client gives
2177 static NTSTATUS openat_pathref_fsp_case_insensitive(
2178 struct files_struct *dirfsp,
2179 struct smb_filename *smb_fname_rel,
2182 const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2183 DATA_BLOB cache_key = { .data = NULL, };
2184 char *found_name = NULL;
2188 SET_STAT_INVALID(smb_fname_rel->st);
2190 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2192 if (NT_STATUS_IS_OK(status)) {
2193 return NT_STATUS_OK;
2196 if (VALID_STAT(smb_fname_rel->st)) {
2198 * We got an error although the object existed. Might
2199 * be a symlink we don't want.
2204 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2206 * Only retry on ENOENT
2211 if (posix || dirfsp->conn->case_sensitive) {
2213 * Only return case insensitive if required
2218 if (lp_stat_cache()) {
2219 char *base_name = smb_fname_rel->base_name;
2220 DATA_BLOB value = { .data = NULL };
2222 ok = get_real_filename_cache_key(
2223 talloc_tos(), dirfsp, base_name, &cache_key);
2226 * probably ENOMEM, just bail
2231 DO_PROFILE_INC(statcache_lookups);
2233 ok = memcache_lookup(
2234 NULL, GETREALFILENAME_CACHE, cache_key, &value);
2236 DO_PROFILE_INC(statcache_misses);
2239 DO_PROFILE_INC(statcache_hits);
2241 TALLOC_FREE(smb_fname_rel->base_name);
2242 smb_fname_rel->base_name = talloc_memdup(
2243 smb_fname_rel, value.data, value.length);
2244 if (smb_fname_rel->base_name == NULL) {
2245 TALLOC_FREE(cache_key.data);
2246 return NT_STATUS_NO_MEMORY;
2249 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2250 if (NT_STATUS_IS_OK(status)) {
2251 TALLOC_FREE(cache_key.data);
2252 return NT_STATUS_OK;
2255 memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
2259 status = get_real_filename_at(
2260 dirfsp, smb_fname_rel->base_name, smb_fname_rel, &found_name);
2261 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2262 (ucf_flags & UCF_PREP_CREATEFILE)) {
2266 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2269 if (NT_STATUS_IS_OK(status)) {
2270 TALLOC_FREE(smb_fname_rel->base_name);
2271 smb_fname_rel->base_name = found_name;
2273 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2276 if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
2278 .data = (uint8_t *)smb_fname_rel->base_name,
2279 .length = strlen(smb_fname_rel->base_name) + 1,
2282 memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
2285 TALLOC_FREE(cache_key.data);
2291 * Split up name_in as sent by the client into a directory pathref fsp
2292 * and a relative smb_filename.
2294 static const char *previous_slash(const char *name_in, const char *slash)
2296 const char *prev = name_in;
2299 const char *next = strchr_m(prev, '/');
2301 SMB_ASSERT(next != NULL); /* we have at least one slash */
2303 if (next == slash) {
2310 if (prev == name_in) {
2311 /* no previous slash */
2318 static char *symlink_target_path(
2319 TALLOC_CTX *mem_ctx,
2320 const char *name_in,
2321 const char *substitute,
2324 size_t name_in_len = strlen(name_in);
2325 const char *p_unparsed = NULL;
2326 const char *parent = NULL;
2329 SMB_ASSERT(unparsed <= name_in_len);
2331 p_unparsed = name_in + (name_in_len - unparsed);
2333 if (substitute[0] == '/') {
2334 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
2338 if (unparsed == 0) {
2339 parent = strrchr_m(name_in, '/');
2341 parent = previous_slash(name_in, p_unparsed);
2344 if (parent == NULL) {
2345 /* no previous slash */
2349 ret = talloc_asprintf(
2352 (int)(parent - name_in),
2360 * Split up name_in as sent by the client into a directory pathref fsp
2361 * and a relative smb_filename.
2363 static NTSTATUS filename_convert_dirfsp_nosymlink(
2364 TALLOC_CTX *mem_ctx,
2365 connection_struct *conn,
2366 const char *name_in,
2369 struct files_struct **_dirfsp,
2370 struct smb_filename **_smb_fname,
2374 struct smb_filename *smb_dirname = NULL;
2375 struct smb_filename *smb_fname_rel = NULL;
2376 struct smb_filename *smb_fname = NULL;
2377 const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2378 char *dirname = NULL;
2379 const char *fname_rel = NULL;
2380 const char *streamname = NULL;
2381 char *saved_streamname = NULL;
2382 struct files_struct *base_fsp = NULL;
2384 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2386 if (ucf_flags & UCF_DFS_PATHNAME) {
2388 NTTIME dfs_twrp = 0;
2389 status = dfs_redirect(
2394 !conn->sconn->using_smb2,
2397 if (!NT_STATUS_IS_OK(status)) {
2398 DBG_DEBUG("dfs_redirect "
2399 "failed for name %s with %s\n",
2405 ucf_flags &= ~UCF_DFS_PATHNAME;
2406 if (twrp == 0 && dfs_twrp != 0) {
2411 if (is_fake_file_path(name_in)) {
2412 smb_fname = synthetic_smb_fname_split(mem_ctx, name_in, posix);
2413 if (smb_fname == NULL) {
2414 return NT_STATUS_NO_MEMORY;
2416 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2417 smb_fname->st.st_ex_btime =
2418 (struct timespec){0, SAMBA_UTIME_OMIT};
2419 smb_fname->st.st_ex_atime =
2420 (struct timespec){0, SAMBA_UTIME_OMIT};
2421 smb_fname->st.st_ex_mtime =
2422 (struct timespec){0, SAMBA_UTIME_OMIT};
2423 smb_fname->st.st_ex_ctime =
2424 (struct timespec){0, SAMBA_UTIME_OMIT};
2426 *_dirfsp = conn->cwd_fsp;
2427 *_smb_fname = smb_fname;
2428 return NT_STATUS_OK;
2432 * Catch an invalid path of "." before we
2433 * call filename_split_lcomp(). We need to
2434 * do this as filename_split_lcomp() will
2435 * use "." for the missing relative component
2436 * when an empty name_in path is sent by
2439 if (ISDOT(name_in)) {
2440 status = NT_STATUS_OBJECT_NAME_INVALID;
2444 ok = filename_split_lcomp(
2452 status = NT_STATUS_NO_MEMORY;
2457 bool name_has_wild = ms_has_wild(dirname);
2458 name_has_wild |= ms_has_wild(fname_rel);
2459 if (name_has_wild) {
2460 status = NT_STATUS_OBJECT_NAME_INVALID;
2465 if (dirname[0] == '\0') {
2466 status = synthetic_pathref(
2473 posix ? SMB_FILENAME_POSIX_PATH : 0,
2476 char *substitute = NULL;
2477 size_t unparsed = 0;
2479 status = openat_pathref_dirfsp_nosymlink(
2488 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
2490 size_t name_in_len = strlen(name_in);
2491 size_t dirname_len = strlen(dirname);
2493 SMB_ASSERT(name_in_len >= dirname_len);
2495 *_substitute = substitute;
2496 *_unparsed = unparsed + (name_in_len - dirname_len);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 DBG_DEBUG("opening directory %s failed: %s\n",
2506 TALLOC_FREE(dirname);
2508 if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
2509 /* MS-DFS error must propagate back out. */
2513 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2515 * Except ACCESS_DENIED, everything else leads
2516 * to PATH_NOT_FOUND.
2518 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2524 if (!VALID_STAT_OF_DIR(smb_dirname->st)) {
2525 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2530 * Only look at bad last component values
2531 * once we know we have a valid directory. That
2532 * way we won't confuse error messages from
2533 * opening the directory path with error
2534 * messages from a bad last component.
2537 /* Relative filename can't be empty */
2538 if (fname_rel[0] == '\0') {
2539 status = NT_STATUS_OBJECT_NAME_INVALID;
2543 /* Relative filename can't be ".." */
2544 if (ISDOTDOT(fname_rel)) {
2545 status = NT_STATUS_OBJECT_NAME_INVALID;
2548 /* Relative name can only be dot if directory is empty. */
2549 if (ISDOT(fname_rel) && dirname[0] != '\0') {
2550 status = NT_STATUS_OBJECT_NAME_INVALID;
2554 TALLOC_FREE(dirname);
2556 smb_fname_rel = synthetic_smb_fname(
2562 posix ? SMB_FILENAME_POSIX_PATH : 0);
2563 if (smb_fname_rel == NULL) {
2564 status = NT_STATUS_NO_MEMORY;
2568 if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
2569 is_named_stream(smb_fname_rel)) {
2571 * Find the base_fsp first without the stream.
2573 saved_streamname = smb_fname_rel->stream_name;
2574 smb_fname_rel->stream_name = NULL;
2577 status = normalize_filename_case(
2578 conn, smb_fname_rel->base_name, ucf_flags);
2579 if (!NT_STATUS_IS_OK(status)) {
2580 DBG_ERR("normalize_filename_case %s failed: %s\n",
2581 smb_fname_rel->base_name,
2586 status = openat_pathref_fsp_case_insensitive(
2587 smb_dirname->fsp, smb_fname_rel, ucf_flags);
2589 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2591 char *normalized = NULL;
2593 if (VALID_STAT(smb_fname_rel->st)) {
2595 * If we're on an MSDFS share, see if this is
2598 if (lp_host_msdfs() &&
2599 lp_msdfs_root(SNUM(conn)) &&
2600 S_ISLNK(smb_fname_rel->st.st_ex_mode) &&
2601 is_msdfs_link(smb_dirname->fsp, smb_fname_rel))
2603 status = NT_STATUS_PATH_NOT_COVERED;
2607 #if defined(WITH_SMB1SERVER)
2609 * In SMB1 posix mode, if this is a symlink,
2610 * allow access to the name with a NULL smb_fname->fsp.
2612 if (!conn->sconn->using_smb2 &&
2614 S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
2615 SMB_ASSERT(smb_fname_rel->fsp == NULL);
2616 SMB_ASSERT(streamname == NULL);
2618 smb_fname = full_path_from_dirfsp_atname(
2622 if (smb_fname == NULL) {
2623 status = NT_STATUS_NO_MEMORY;
2630 * NT_STATUS_OBJECT_NAME_NOT_FOUND is
2631 * misleading: The object exists but might be
2632 * a symlink pointing outside the share.
2638 * Creating a new file
2641 status = filename_convert_normalize_new(
2644 smb_fname_rel->base_name,
2646 if (!NT_STATUS_IS_OK(status)) {
2647 DBG_DEBUG("filename_convert_normalize_new failed: "
2652 if (normalized != NULL) {
2653 smb_fname_rel->base_name = normalized;
2656 smb_fname_rel->stream_name = saved_streamname;
2658 smb_fname = full_path_from_dirfsp_atname(
2659 mem_ctx, smb_dirname->fsp, smb_fname_rel);
2660 if (smb_fname == NULL) {
2661 status = NT_STATUS_NO_MEMORY;
2667 if (!NT_STATUS_IS_OK(status)) {
2671 if (saved_streamname == NULL) {
2672 /* smb_fname must be allocated off mem_ctx. */
2673 smb_fname = cp_smb_filename(mem_ctx,
2674 smb_fname_rel->fsp->fsp_name);
2675 if (smb_fname == NULL) {
2678 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
2679 if (!NT_STATUS_IS_OK(status)) {
2685 base_fsp = smb_fname_rel->fsp;
2686 smb_fname_fsp_unlink(smb_fname_rel);
2687 SET_STAT_INVALID(smb_fname_rel->st);
2689 smb_fname_rel->stream_name = saved_streamname;
2691 status = open_stream_pathref_fsp(&base_fsp, smb_fname_rel);
2693 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
2694 !conn->case_sensitive) {
2697 status = get_real_stream_name(
2700 smb_fname_rel->stream_name,
2703 if (NT_STATUS_IS_OK(status)) {
2704 smb_fname_rel->stream_name = found;
2706 status = open_stream_pathref_fsp(
2707 &base_fsp, smb_fname_rel);
2711 if (NT_STATUS_IS_OK(status)) {
2712 /* smb_fname must be allocated off mem_ctx. */
2713 smb_fname = cp_smb_filename(mem_ctx,
2714 smb_fname_rel->fsp->fsp_name);
2715 if (smb_fname == NULL) {
2718 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
2719 if (!NT_STATUS_IS_OK(status)) {
2725 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2727 * Creating a new stream
2729 * We should save the already-open base fsp for
2730 * create_file_unixpath() somehow.
2732 smb_fname = full_path_from_dirfsp_atname(
2733 mem_ctx, smb_dirname->fsp, smb_fname_rel);
2734 if (smb_fname == NULL) {
2735 status = NT_STATUS_NO_MEMORY;
2741 if (!NT_STATUS_IS_OK(status)) {
2746 *_dirfsp = smb_dirname->fsp;
2747 *_smb_fname = smb_fname;
2749 smb_fname_fsp_unlink(smb_fname_rel);
2750 TALLOC_FREE(smb_fname_rel);
2751 return NT_STATUS_OK;
2754 TALLOC_FREE(dirname);
2755 TALLOC_FREE(smb_dirname);
2756 TALLOC_FREE(smb_fname_rel);
2760 NTSTATUS filename_convert_dirfsp(
2761 TALLOC_CTX *mem_ctx,
2762 connection_struct *conn,
2763 const char *name_in,
2766 struct files_struct **_dirfsp,
2767 struct smb_filename **_smb_fname)
2769 char *substitute = NULL;
2770 size_t unparsed = 0;
2772 char *target = NULL;
2773 char *abs_target = NULL;
2774 char *abs_target_canon = NULL;
2775 size_t symlink_redirects = 0;
2779 if (symlink_redirects > 40) {
2780 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2783 status = filename_convert_dirfsp_nosymlink(
2794 if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
2798 if (!lp_follow_symlinks(SNUM(conn))) {
2799 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2803 * Right now, SMB2 and SMB1 always traverse symlinks
2804 * within the share. SMB1+POSIX traverses non-terminal
2805 * symlinks within the share.
2807 * When we add SMB2+POSIX we need to return
2808 * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
2809 * symlink target data read below if SMB2+POSIX has
2810 * UCF_POSIX_PATHNAMES set to cause the client to
2811 * resolve all symlinks locally.
2814 target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
2815 if (target == NULL) {
2816 return NT_STATUS_NO_MEMORY;
2819 DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
2825 if (target[0] == '/') {
2826 abs_target = target;
2828 abs_target = talloc_asprintf(
2829 mem_ctx, "%s/%s", conn->connectpath, target);
2830 if (abs_target == NULL) {
2831 return NT_STATUS_NO_MEMORY;
2835 abs_target_canon = canonicalize_absolute_path(mem_ctx, abs_target);
2836 if (abs_target_canon == NULL) {
2837 return NT_STATUS_NO_MEMORY;
2840 DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
2845 strlen(conn->connectpath)) == 0;
2847 DBG_DEBUG("wide link to %s\n", abs_target_canon);
2848 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2851 name_in = talloc_strdup(
2852 mem_ctx, abs_target_canon + strlen(conn->connectpath) + 1);
2854 symlink_redirects += 1;
2860 * Build the full path from a dirfsp and dirfsp relative name
2862 struct smb_filename *full_path_from_dirfsp_atname(
2863 TALLOC_CTX *mem_ctx,
2864 const struct files_struct *dirfsp,
2865 const struct smb_filename *atname)
2867 struct smb_filename *fname = NULL;
2870 if (dirfsp == dirfsp->conn->cwd_fsp ||
2871 ISDOT(dirfsp->fsp_name->base_name) ||
2872 atname->base_name[0] == '/')
2874 path = talloc_strdup(mem_ctx, atname->base_name);
2876 path = talloc_asprintf(mem_ctx, "%s/%s",
2877 dirfsp->fsp_name->base_name,
2884 fname = synthetic_smb_fname(mem_ctx,
2886 atname->stream_name,
2891 if (fname == NULL) {