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 struct smb_filename *smb_fname = NULL;
1883 char *last_slash = NULL;
1889 if (ucf_flags & UCF_DFS_PATHNAME) {
1890 status = dfs_redirect(ctx,
1894 !conn->sconn->using_smb2,
1897 if (!NT_STATUS_IS_OK(status)) {
1898 DBG_DEBUG("dfs_redirect "
1899 "failed for name %s with %s\n",
1904 filename_in = fname;
1905 ucf_flags &= ~UCF_DFS_PATHNAME;
1909 * NB. We don't need to care about
1910 * is_fake_file_path(filename_in) here as these
1911 * code paths don't ever return original_lcomp
1915 if (ucf_flags & UCF_GMT_PATHNAME) {
1917 * Ensure we don't return a @GMT
1918 * value as the last component.
1920 smb_fname = synthetic_smb_fname(ctx,
1926 if (smb_fname == NULL) {
1930 status = canonicalize_snapshot_path(smb_fname,
1933 if (!NT_STATUS_IS_OK(status)) {
1935 TALLOC_FREE(smb_fname);
1938 filename_in = smb_fname->base_name;
1940 last_slash = strrchr(filename_in, '/');
1941 if (last_slash != NULL) {
1942 orig_lcomp = talloc_strdup(ctx, last_slash+1);
1944 orig_lcomp = talloc_strdup(ctx, filename_in);
1946 /* We're done with any temp names here. */
1947 TALLOC_FREE(smb_fname);
1949 if (orig_lcomp == NULL) {
1952 status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
1953 if (!NT_STATUS_IS_OK(status)) {
1954 TALLOC_FREE(orig_lcomp);
1961 * Go through all the steps to validate a filename.
1963 * @param ctx talloc_ctx to allocate memory with.
1964 * @param conn connection struct for vfs calls.
1965 * @param smbreq SMB request if we're using privileges.
1966 * @param name_in The unconverted name.
1967 * @param ucf_flags flags to pass through to unix_convert().
1968 * @param twrp Optional VSS time
1969 * @param p_cont_wcard If not NULL, will be set to true if the dfs path
1970 * resolution detects a wildcard.
1971 * @param _smb_fname The final converted name will be allocated if the
1972 * return is NT_STATUS_OK.
1974 * @return NT_STATUS_OK if all operations completed successfully, appropriate
1977 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1978 connection_struct *conn,
1979 const char *name_in,
1982 struct smb_filename **_smb_fname)
1984 struct smb_filename *smb_fname = NULL;
1989 if (ucf_flags & UCF_DFS_PATHNAME) {
1991 NTTIME dfs_twrp = 0;
1992 status = dfs_redirect(ctx, conn,
1995 !conn->sconn->using_smb2,
1998 if (!NT_STATUS_IS_OK(status)) {
1999 DBG_DEBUG("dfs_redirect "
2000 "failed for name %s with %s\n",
2006 ucf_flags &= ~UCF_DFS_PATHNAME;
2007 if (twrp == 0 && dfs_twrp != 0) {
2012 if (is_fake_file_path(name_in)) {
2013 smb_fname = synthetic_smb_fname_split(ctx,
2015 (ucf_flags & UCF_POSIX_PATHNAMES));
2016 if (smb_fname == NULL) {
2017 return NT_STATUS_NO_MEMORY;
2019 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2020 smb_fname->st.st_ex_btime = (struct timespec){0, SAMBA_UTIME_OMIT};
2021 smb_fname->st.st_ex_atime = (struct timespec){0, SAMBA_UTIME_OMIT};
2022 smb_fname->st.st_ex_mtime = (struct timespec){0, SAMBA_UTIME_OMIT};
2023 smb_fname->st.st_ex_ctime = (struct timespec){0, SAMBA_UTIME_OMIT};
2025 *_smb_fname = smb_fname;
2026 return NT_STATUS_OK;
2029 status = unix_convert(ctx, conn, name_in, twrp, &smb_fname, ucf_flags);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 DBG_DEBUG("unix_convert failed "
2032 "for name %s with %s\n",
2038 if ((ucf_flags & UCF_POSIX_PATHNAMES) &&
2039 VALID_STAT(smb_fname->st) &&
2040 S_ISLNK(smb_fname->st.st_ex_mode))
2042 status = check_veto_path(conn, smb_fname);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 TALLOC_FREE(smb_fname);
2048 status = check_name(conn, smb_fname);
2050 if (!NT_STATUS_IS_OK(status)) {
2051 DBG_NOTICE("check_name failed "
2052 "for name %s with %s\n",
2053 smb_fname_str_dbg(smb_fname),
2055 TALLOC_FREE(smb_fname);
2059 if (!VALID_STAT(smb_fname->st)) {
2060 DBG_DEBUG("[%s] does not exist, skipping pathref fsp\n",
2061 smb_fname_str_dbg(smb_fname));
2062 *_smb_fname = smb_fname;
2063 return NT_STATUS_OK;
2066 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
2067 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2069 * We deal with symlinks here as we do in
2070 * SMB_VFS_CREATE_FILE(): return success for POSIX clients with
2071 * the notable difference that there will be no fsp in
2074 * For Windows (non POSIX) clients fail with
2075 * NT_STATUS_OBJECT_NAME_NOT_FOUND.
2077 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH &&
2078 S_ISLNK(smb_fname->st.st_ex_mode))
2080 status = NT_STATUS_OK;
2083 if (!NT_STATUS_IS_OK(status)) {
2084 DBG_DEBUG("openat_pathref_fsp [%s] failed: %s\n",
2085 smb_fname_str_dbg(smb_fname),
2090 *_smb_fname = smb_fname;
2095 * Strip a @GMT component from an SMB1-DFS path. Could be anywhere
2099 static char *strip_gmt_from_raw_dfs(TALLOC_CTX *ctx,
2100 const char *name_in,
2101 bool posix_pathnames,
2105 struct smb_filename *smb_fname = NULL;
2106 char *name_out = NULL;
2108 smb_fname = synthetic_smb_fname(ctx,
2114 if (smb_fname == NULL) {
2117 if (!posix_pathnames) {
2119 * Raw DFS names are still '\\' separated.
2120 * canonicalize_snapshot_path() only works
2121 * on '/' separated paths. Convert.
2123 string_replace(smb_fname->base_name, '\\', '/');
2125 status = canonicalize_snapshot_path(smb_fname,
2128 if (!NT_STATUS_IS_OK(status)) {
2129 TALLOC_FREE(smb_fname);
2132 if (!posix_pathnames) {
2133 /* Replace as raw DFS names. */
2134 string_replace(smb_fname->base_name, '/', '\\');
2136 name_out = talloc_strdup(ctx, smb_fname->base_name);
2137 *_twrp = smb_fname->twrp;
2138 TALLOC_FREE(smb_fname);
2143 * Deal with the SMB1 semantics of sending a pathname with a
2144 * wildcard as the terminal component for a SMB1search or
2148 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
2149 connection_struct *conn,
2150 const char *name_in,
2152 struct smb_filename **_smb_fname_out,
2158 struct smb_filename *smb_fname = NULL;
2159 bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
2161 TALLOC_CTX *frame = talloc_stackframe();
2163 *_smb_fname_out = NULL;
2166 DBG_DEBUG("name_in: %s\n", name_in);
2168 if (ucf_flags & UCF_DFS_PATHNAME) {
2170 * We've been given a raw DFS pathname.
2171 * In Windows mode this is separated by '\\'
2174 * We need to remove the last component
2175 * which must be a wildcard before passing
2176 * to dfs_redirect(). But the last component
2177 * may also be a @GMT- token so we have to
2178 * remove that first.
2180 char path_sep = posix_pathnames ? '/' : '\\';
2182 char *name_in_copy = NULL;
2183 char *last_component = NULL;
2185 /* Work on a copy of name_in. */
2186 if (ucf_flags & UCF_GMT_PATHNAME) {
2187 name_in_copy = strip_gmt_from_raw_dfs(frame,
2191 ucf_flags &= ~UCF_GMT_PATHNAME;
2193 name_in_copy = talloc_strdup(frame, name_in);
2195 if (name_in_copy == NULL) {
2197 return NT_STATUS_NO_MEMORY;
2201 * Now we know that the last component is the
2202 * wildcard. Copy it and truncate to remove it.
2204 p = strrchr_m(name_in_copy, path_sep);
2206 last_component = talloc_strdup(frame, name_in_copy);
2207 name_in_copy[0] = '\0';
2209 last_component = talloc_strdup(frame, p+1);
2212 if (last_component == NULL) {
2214 return NT_STATUS_NO_MEMORY;
2217 DBG_DEBUG("name_in_copy: %s\n", name_in);
2220 * Now we can call dfs_redirect()
2221 * on the name without wildcard.
2223 status = dfs_redirect(frame,
2227 !conn->sconn->using_smb2,
2230 if (!NT_STATUS_IS_OK(status)) {
2231 DBG_DEBUG("dfs_redirect "
2232 "failed for name %s with %s\n",
2238 /* Add the last component back. */
2239 if (fname[0] == '\0') {
2240 name_in = talloc_strdup(frame, last_component);
2242 name_in = talloc_asprintf(frame,
2248 if (name_in == NULL) {
2250 return NT_STATUS_NO_MEMORY;
2252 ucf_flags &= ~UCF_DFS_PATHNAME;
2254 DBG_DEBUG("After DFS redirect name_in: %s\n", name_in);
2257 smb_fname = synthetic_smb_fname(frame,
2263 SMB_FILENAME_POSIX_PATH : 0);
2264 if (smb_fname == NULL) {
2266 return NT_STATUS_NO_MEMORY;
2269 /* Canonicalize any @GMT- paths. */
2270 status = canonicalize_snapshot_path(smb_fname, ucf_flags, twrp);
2271 if (!NT_STATUS_IS_OK(status)) {
2276 /* Get the original lcomp. */
2277 mask = get_original_lcomp(frame,
2283 return NT_STATUS_NO_MEMORY;
2286 if (mask[0] == '\0') {
2287 /* Windows and OS/2 systems treat search on the root as * */
2289 mask = talloc_strdup(frame, "*");
2292 return NT_STATUS_NO_MEMORY;
2296 DBG_DEBUG("mask = %s\n", mask);
2299 * Remove the terminal component so
2300 * filename_convert never sees the mask.
2302 p = strrchr_m(smb_fname->base_name,'/');
2304 /* filename_convert handles a '\0' base_name. */
2305 smb_fname->base_name[0] = '\0';
2310 DBG_DEBUG("For filename_convert: smb_fname = %s\n",
2311 smb_fname_str_dbg(smb_fname));
2313 /* Convert the parent directory path. */
2314 status = filename_convert(frame,
2316 smb_fname->base_name,
2321 if (NT_STATUS_IS_OK(status)) {
2322 *_smb_fname_out = talloc_move(ctx, &smb_fname);
2323 *_mask_out = talloc_move(ctx, &mask);
2325 DBG_DEBUG("filename_convert error for %s: %s\n",
2326 smb_fname_str_dbg(smb_fname),
2335 * Get the correct capitalized stream name hanging off
2336 * base_fsp. Equivalent of get_real_filename(), but for streams.
2338 static NTSTATUS get_real_stream_name(
2339 TALLOC_CTX *mem_ctx,
2340 struct files_struct *base_fsp,
2341 const char *stream_name,
2344 unsigned int i, num_streams = 0;
2345 struct stream_struct *streams = NULL;
2348 status = vfs_fstreaminfo(
2349 base_fsp, talloc_tos(), &num_streams, &streams);
2350 if (!NT_STATUS_IS_OK(status)) {
2354 for (i=0; i<num_streams; i++) {
2355 bool equal = sname_equal(stream_name, streams[i].name, false);
2357 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
2360 equal ? "" : "not ");
2363 *_found = talloc_move(mem_ctx, &streams[i].name);
2364 TALLOC_FREE(streams);
2365 return NT_STATUS_OK;
2369 TALLOC_FREE(streams);
2370 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2373 static bool filename_split_lcomp(
2374 TALLOC_CTX *mem_ctx,
2375 const char *name_in,
2378 const char **_fname_rel,
2379 const char **_streamname)
2381 const char *lcomp = NULL;
2382 const char *fname_rel = NULL;
2383 const char *streamname = NULL;
2384 char *dirname = NULL;
2386 if (name_in[0] == '\0') {
2388 dirname = talloc_strdup(mem_ctx, "");
2389 if (dirname == NULL) {
2395 lcomp = strrchr_m(name_in, '/');
2396 if (lcomp != NULL) {
2397 fname_rel = lcomp+1;
2398 dirname = talloc_strndup(mem_ctx, name_in, lcomp - name_in);
2399 if (dirname == NULL) {
2406 * No slash, dir is emtpy
2408 dirname = talloc_strdup(mem_ctx, "");
2409 if (dirname == NULL) {
2413 if (!posix && (name_in[0] == ':')) {
2415 * Special case for stream on root directory
2418 streamname = name_in;
2422 fname_rel = name_in;
2426 streamname = strchr_m(fname_rel, ':');
2428 if (streamname != NULL) {
2429 fname_rel = talloc_strndup(
2432 streamname - fname_rel);
2433 if (fname_rel == NULL) {
2434 TALLOC_FREE(dirname);
2441 *_dirname = dirname;
2442 *_fname_rel = fname_rel;
2443 *_streamname = streamname;
2448 * Create the correct capitalization of a file name to be created.
2450 static NTSTATUS filename_convert_normalize_new(
2451 TALLOC_CTX *mem_ctx,
2452 struct connection_struct *conn,
2456 char *name = name_in;
2458 *_normalized = NULL;
2460 if (!conn->case_preserve ||
2461 (mangle_is_8_3(name, false,
2463 !conn->short_case_preserve)) {
2465 char *normalized = talloc_strdup(mem_ctx, name);
2466 if (normalized == NULL) {
2467 return NT_STATUS_NO_MEMORY;
2470 strnorm(normalized, lp_default_case(SNUM(conn)));
2474 if (mangle_is_mangled(name, conn->params)) {
2476 char *unmangled = NULL;
2478 found = mangle_lookup_name_from_8_3(
2479 mem_ctx, name, &unmangled, conn->params);
2485 if (name != name_in) {
2486 *_normalized = name;
2489 return NT_STATUS_OK;
2493 * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
2494 * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
2495 * the first attempt based on the filename sent by the client gives
2498 static NTSTATUS openat_pathref_fsp_case_insensitive(
2499 struct files_struct *dirfsp,
2500 struct smb_filename *smb_fname_rel,
2503 const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2504 DATA_BLOB cache_key = { .data = NULL, };
2505 char *found_name = NULL;
2509 SET_STAT_INVALID(smb_fname_rel->st);
2511 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2513 if (NT_STATUS_IS_OK(status)) {
2514 return NT_STATUS_OK;
2517 if (VALID_STAT(smb_fname_rel->st)) {
2519 * We got an error although the object existed. Might
2520 * be a symlink we don't want.
2525 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2527 * Only retry on ENOENT
2532 if (posix || dirfsp->conn->case_sensitive) {
2534 * Only return case insensitive if required
2539 if (lp_stat_cache()) {
2540 char *base_name = smb_fname_rel->base_name;
2541 DATA_BLOB value = { .data = NULL };
2543 ok = get_real_filename_cache_key(
2544 talloc_tos(), dirfsp, base_name, &cache_key);
2547 * probably ENOMEM, just bail
2552 DO_PROFILE_INC(statcache_lookups);
2554 ok = memcache_lookup(
2555 NULL, GETREALFILENAME_CACHE, cache_key, &value);
2557 DO_PROFILE_INC(statcache_misses);
2560 DO_PROFILE_INC(statcache_hits);
2562 TALLOC_FREE(smb_fname_rel->base_name);
2563 smb_fname_rel->base_name = talloc_memdup(
2564 smb_fname_rel, value.data, value.length);
2565 if (smb_fname_rel->base_name == NULL) {
2566 TALLOC_FREE(cache_key.data);
2567 return NT_STATUS_NO_MEMORY;
2570 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2571 if (NT_STATUS_IS_OK(status)) {
2572 TALLOC_FREE(cache_key.data);
2573 return NT_STATUS_OK;
2576 memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
2580 status = get_real_filename_at(
2581 dirfsp, smb_fname_rel->base_name, smb_fname_rel, &found_name);
2582 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2583 (ucf_flags & UCF_PREP_CREATEFILE)) {
2587 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2590 if (NT_STATUS_IS_OK(status)) {
2591 TALLOC_FREE(smb_fname_rel->base_name);
2592 smb_fname_rel->base_name = found_name;
2594 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2597 if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
2599 .data = (uint8_t *)smb_fname_rel->base_name,
2600 .length = strlen(smb_fname_rel->base_name) + 1,
2603 memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
2606 TALLOC_FREE(cache_key.data);
2612 * Split up name_in as sent by the client into a directory pathref fsp
2613 * and a relative smb_filename.
2615 static const char *previous_slash(const char *name_in, const char *slash)
2617 const char *prev = name_in;
2620 const char *next = strchr_m(prev, '/');
2622 SMB_ASSERT(next != NULL); /* we have at least one slash */
2624 if (next == slash) {
2631 if (prev == name_in) {
2632 /* no previous slash */
2639 static char *symlink_target_path(
2640 TALLOC_CTX *mem_ctx,
2641 const char *name_in,
2642 const char *substitute,
2645 size_t name_in_len = strlen(name_in);
2646 const char *p_unparsed = NULL;
2647 const char *parent = NULL;
2650 SMB_ASSERT(unparsed <= name_in_len);
2652 p_unparsed = name_in + (name_in_len - unparsed);
2654 if (substitute[0] == '/') {
2655 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
2659 if (unparsed == 0) {
2660 parent = strrchr_m(name_in, '/');
2662 parent = previous_slash(name_in, p_unparsed);
2665 if (parent == NULL) {
2666 /* no previous slash */
2670 ret = talloc_asprintf(
2673 (int)(parent - name_in),
2681 * Split up name_in as sent by the client into a directory pathref fsp
2682 * and a relative smb_filename.
2684 static NTSTATUS filename_convert_dirfsp_nosymlink(
2685 TALLOC_CTX *mem_ctx,
2686 connection_struct *conn,
2687 const char *name_in,
2690 struct files_struct **_dirfsp,
2691 struct smb_filename **_smb_fname,
2695 struct smb_filename *smb_dirname = NULL;
2696 struct smb_filename *smb_fname_rel = NULL;
2697 struct smb_filename *smb_fname = NULL;
2698 const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2699 char *dirname = NULL;
2700 const char *fname_rel = NULL;
2701 const char *streamname = NULL;
2702 char *saved_streamname = NULL;
2703 struct files_struct *base_fsp = NULL;
2705 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2707 if (ucf_flags & UCF_DFS_PATHNAME) {
2709 NTTIME dfs_twrp = 0;
2710 status = dfs_redirect(
2715 !conn->sconn->using_smb2,
2718 if (!NT_STATUS_IS_OK(status)) {
2719 DBG_DEBUG("dfs_redirect "
2720 "failed for name %s with %s\n",
2726 ucf_flags &= ~UCF_DFS_PATHNAME;
2727 if (twrp == 0 && dfs_twrp != 0) {
2732 if (is_fake_file_path(name_in) || conn->printer) {
2733 smb_fname = synthetic_smb_fname_split(mem_ctx, name_in, posix);
2734 if (smb_fname == NULL) {
2735 return NT_STATUS_NO_MEMORY;
2737 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2738 smb_fname->st.st_ex_btime =
2739 (struct timespec){0, SAMBA_UTIME_OMIT};
2740 smb_fname->st.st_ex_atime =
2741 (struct timespec){0, SAMBA_UTIME_OMIT};
2742 smb_fname->st.st_ex_mtime =
2743 (struct timespec){0, SAMBA_UTIME_OMIT};
2744 smb_fname->st.st_ex_ctime =
2745 (struct timespec){0, SAMBA_UTIME_OMIT};
2747 *_dirfsp = conn->cwd_fsp;
2748 *_smb_fname = smb_fname;
2749 return NT_STATUS_OK;
2753 * Catch an invalid path of "." before we
2754 * call filename_split_lcomp(). We need to
2755 * do this as filename_split_lcomp() will
2756 * use "." for the missing relative component
2757 * when an empty name_in path is sent by
2760 if (ISDOT(name_in)) {
2761 status = NT_STATUS_OBJECT_NAME_INVALID;
2765 ok = filename_split_lcomp(
2773 status = NT_STATUS_NO_MEMORY;
2778 bool name_has_wild = ms_has_wild(dirname);
2779 name_has_wild |= ms_has_wild(fname_rel);
2780 if (name_has_wild) {
2781 status = NT_STATUS_OBJECT_NAME_INVALID;
2786 if (dirname[0] == '\0') {
2787 status = synthetic_pathref(
2794 posix ? SMB_FILENAME_POSIX_PATH : 0,
2797 char *substitute = NULL;
2798 size_t unparsed = 0;
2800 status = openat_pathref_dirfsp_nosymlink(
2809 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
2811 size_t name_in_len = strlen(name_in);
2812 size_t dirname_len = strlen(dirname);
2814 SMB_ASSERT(name_in_len >= dirname_len);
2816 *_substitute = substitute;
2817 *_unparsed = unparsed + (name_in_len - dirname_len);
2823 if (!NT_STATUS_IS_OK(status)) {
2824 DBG_DEBUG("opening directory %s failed: %s\n",
2827 TALLOC_FREE(dirname);
2829 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2831 * Except ACCESS_DENIED, everything else leads
2832 * to PATH_NOT_FOUND.
2834 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2840 if (!VALID_STAT_OF_DIR(smb_dirname->st)) {
2841 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2846 * Only look at bad last component values
2847 * once we know we have a valid directory. That
2848 * way we won't confuse error messages from
2849 * opening the directory path with error
2850 * messages from a bad last component.
2853 /* Relative filename can't be empty */
2854 if (fname_rel[0] == '\0') {
2855 status = NT_STATUS_OBJECT_NAME_INVALID;
2859 /* Relative filename can't be ".." */
2860 if (ISDOTDOT(fname_rel)) {
2861 status = NT_STATUS_OBJECT_NAME_INVALID;
2864 /* Relative name can only be dot if directory is empty. */
2865 if (ISDOT(fname_rel) && dirname[0] != '\0') {
2866 status = NT_STATUS_OBJECT_NAME_INVALID;
2870 TALLOC_FREE(dirname);
2872 smb_fname_rel = synthetic_smb_fname(
2878 posix ? SMB_FILENAME_POSIX_PATH : 0);
2879 if (smb_fname_rel == NULL) {
2880 status = NT_STATUS_NO_MEMORY;
2884 if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
2885 is_named_stream(smb_fname_rel)) {
2887 * Find the base_fsp first without the stream.
2889 saved_streamname = smb_fname_rel->stream_name;
2890 smb_fname_rel->stream_name = NULL;
2893 status = normalize_filename_case(
2894 conn, smb_fname_rel->base_name, ucf_flags);
2895 if (!NT_STATUS_IS_OK(status)) {
2896 DBG_ERR("normalize_filename_case %s failed: %s\n",
2897 smb_fname_rel->base_name,
2902 status = openat_pathref_fsp_case_insensitive(
2903 smb_dirname->fsp, smb_fname_rel, ucf_flags);
2905 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2907 char *normalized = NULL;
2909 if (VALID_STAT(smb_fname_rel->st)) {
2910 #if defined(WITH_SMB1SERVER)
2912 * In SMB1 posix mode, if this is a symlink,
2913 * allow access to the name with a NULL smb_fname->fsp.
2915 if (!conn->sconn->using_smb2 &&
2917 S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
2918 SMB_ASSERT(smb_fname_rel->fsp == NULL);
2919 SMB_ASSERT(streamname == NULL);
2921 smb_fname = full_path_from_dirfsp_atname(
2925 if (smb_fname == NULL) {
2926 status = NT_STATUS_NO_MEMORY;
2933 * NT_STATUS_OBJECT_NAME_NOT_FOUND is
2934 * misleading: The object exists but might be
2935 * a symlink pointing outside the share.
2941 * Creating a new file
2944 status = filename_convert_normalize_new(
2947 smb_fname_rel->base_name,
2949 if (!NT_STATUS_IS_OK(status)) {
2950 DBG_DEBUG("filename_convert_normalize_new failed: "
2955 if (normalized != NULL) {
2956 smb_fname_rel->base_name = normalized;
2959 smb_fname_rel->stream_name = saved_streamname;
2961 smb_fname = full_path_from_dirfsp_atname(
2962 mem_ctx, smb_dirname->fsp, smb_fname_rel);
2963 if (smb_fname == NULL) {
2964 status = NT_STATUS_NO_MEMORY;
2970 if (!NT_STATUS_IS_OK(status)) {
2974 if (saved_streamname == NULL) {
2975 /* smb_fname must be allocated off mem_ctx. */
2976 smb_fname = cp_smb_filename(mem_ctx,
2977 smb_fname_rel->fsp->fsp_name);
2978 if (smb_fname == NULL) {
2981 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
2982 if (!NT_STATUS_IS_OK(status)) {
2988 base_fsp = smb_fname_rel->fsp;
2989 smb_fname_fsp_unlink(smb_fname_rel);
2990 SET_STAT_INVALID(smb_fname_rel->st);
2992 smb_fname_rel->stream_name = saved_streamname;
2994 status = open_stream_pathref_fsp(&base_fsp, smb_fname_rel);
2996 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
2997 !conn->case_sensitive) {
3000 status = get_real_stream_name(
3003 smb_fname_rel->stream_name,
3006 if (NT_STATUS_IS_OK(status)) {
3007 smb_fname_rel->stream_name = found;
3009 status = open_stream_pathref_fsp(
3010 &base_fsp, smb_fname_rel);
3014 if (NT_STATUS_IS_OK(status)) {
3015 /* smb_fname must be allocated off mem_ctx. */
3016 smb_fname = cp_smb_filename(mem_ctx,
3017 smb_fname_rel->fsp->fsp_name);
3018 if (smb_fname == NULL) {
3021 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
3022 if (!NT_STATUS_IS_OK(status)) {
3028 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3030 * Creating a new stream
3032 * We should save the already-open base fsp for
3033 * create_file_unixpath() somehow.
3035 smb_fname = full_path_from_dirfsp_atname(
3036 mem_ctx, smb_dirname->fsp, smb_fname_rel);
3037 if (smb_fname == NULL) {
3038 status = NT_STATUS_NO_MEMORY;
3044 if (!NT_STATUS_IS_OK(status)) {
3049 *_dirfsp = smb_dirname->fsp;
3050 *_smb_fname = smb_fname;
3052 smb_fname_fsp_unlink(smb_fname_rel);
3053 TALLOC_FREE(smb_fname_rel);
3054 return NT_STATUS_OK;
3057 TALLOC_FREE(dirname);
3058 TALLOC_FREE(smb_dirname);
3059 TALLOC_FREE(smb_fname_rel);
3063 NTSTATUS filename_convert_dirfsp(
3064 TALLOC_CTX *mem_ctx,
3065 connection_struct *conn,
3066 const char *name_in,
3069 struct files_struct **_dirfsp,
3070 struct smb_filename **_smb_fname)
3072 char *substitute = NULL;
3073 size_t unparsed = 0;
3075 char *target = NULL;
3076 char *abs_target = NULL;
3077 char *abs_target_canon = NULL;
3078 size_t symlink_redirects = 0;
3082 if (symlink_redirects > 40) {
3083 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3086 status = filename_convert_dirfsp_nosymlink(
3097 #if defined(WITH_SMB1SERVER)
3099 * This isn't 100% correct, but it gets us close enough
3100 * to the old behavior for SMB1+POSIX libsmbclient. If we went through a
3101 * symlink, and we got NT_STATUS_ACCESS_DENIED on the directory
3102 * containing the target, just don't allow the client to see the
3103 * intermediate path.
3105 if (!conn->sconn->using_smb2 &&
3106 (ucf_flags & UCF_POSIX_PATHNAMES) &&
3107 symlink_redirects > 0 &&
3108 NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3109 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3113 if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
3117 if (!lp_follow_symlinks(SNUM(conn))) {
3118 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3122 * Right now, SMB2 and SMB1 always traverse symlinks
3123 * within the share. SMB1+POSIX traverses non-terminal
3124 * symlinks within the share.
3126 * When we add SMB2+POSIX we need to return
3127 * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
3128 * symlink target data read below if SMB2+POSIX has
3129 * UCF_POSIX_PATHNAMES set to cause the client to
3130 * resolve all symlinks locally.
3133 target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
3134 if (target == NULL) {
3135 return NT_STATUS_NO_MEMORY;
3138 DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
3144 if (target[0] == '/') {
3145 abs_target = target;
3147 abs_target = talloc_asprintf(
3148 mem_ctx, "%s/%s", conn->connectpath, target);
3149 if (abs_target == NULL) {
3150 return NT_STATUS_NO_MEMORY;
3154 abs_target_canon = canonicalize_absolute_path(mem_ctx, abs_target);
3155 if (abs_target_canon == NULL) {
3156 return NT_STATUS_NO_MEMORY;
3159 DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
3164 strlen(conn->connectpath)) == 0;
3166 DBG_DEBUG("wide link to %s\n", abs_target_canon);
3167 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3170 name_in = talloc_strdup(
3171 mem_ctx, abs_target_canon + strlen(conn->connectpath) + 1);
3173 symlink_redirects += 1;
3179 * Build the full path from a dirfsp and dirfsp relative name
3181 struct smb_filename *full_path_from_dirfsp_atname(
3182 TALLOC_CTX *mem_ctx,
3183 const struct files_struct *dirfsp,
3184 const struct smb_filename *atname)
3186 struct smb_filename *fname = NULL;
3189 if (dirfsp == dirfsp->conn->cwd_fsp ||
3190 ISDOT(dirfsp->fsp_name->base_name) ||
3191 atname->base_name[0] == '/')
3193 path = talloc_strdup(mem_ctx, atname->base_name);
3195 path = talloc_asprintf(mem_ctx, "%s/%s",
3196 dirfsp->fsp_name->base_name,
3203 fname = synthetic_smb_fname(mem_ctx,
3205 atname->stream_name,
3210 if (fname == NULL) {