s3: smbd: Remove call to dfs_redirect() from filename_convert_smb1_search_path().
[samba.git] / source3 / smbd / filename.c
1 /*
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
8
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.
13
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.
18
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/>.
21 */
22
23 /*
24  * New hash table stat cache code added by Ying Chen.
25  */
26
27 #include "includes.h"
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"
33
34 static NTSTATUS get_real_filename(connection_struct *conn,
35                                   struct smb_filename *path,
36                                   const char *name,
37                                   TALLOC_CTX *mem_ctx,
38                                   char **found_name);
39
40 static NTSTATUS check_name(connection_struct *conn,
41                            const struct smb_filename *smb_fname);
42
43 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
44 {
45         uint32_t ucf_flags = 0;
46
47         if (req != NULL) {
48                 if (req->posix_pathnames) {
49                         ucf_flags |= UCF_POSIX_PATHNAMES;
50                 }
51                 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
52                         ucf_flags |= UCF_DFS_PATHNAME;
53                 }
54                 if (req->flags2 & FLAGS2_REPARSE_PATH) {
55                         ucf_flags |= UCF_GMT_PATHNAME;
56                 }
57         }
58
59         return ucf_flags;
60 }
61
62 uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
63 {
64         uint32_t ucf_flags = 0;
65
66         ucf_flags |= ucf_flags_from_smb_request(req);
67
68         switch (create_disposition) {
69         case FILE_OPEN:
70         case FILE_OVERWRITE:
71                 break;
72         case FILE_SUPERSEDE:
73         case FILE_CREATE:
74         case FILE_OPEN_IF:
75         case FILE_OVERWRITE_IF:
76                 ucf_flags |= UCF_PREP_CREATEFILE;
77                 break;
78         }
79
80         return ucf_flags;
81 }
82
83 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
84                                   connection_struct *conn,
85                                   struct smb_filename *smb_fname);
86
87 /****************************************************************************
88  Mangle the 2nd name and check if it is then equal to the first name.
89 ****************************************************************************/
90
91 static bool mangled_equal(const char *name1,
92                         const char *name2,
93                         const struct share_params *p)
94 {
95         char mname[13];
96
97         if (!name_to_8_3(name2, mname, False, p)) {
98                 return False;
99         }
100         return strequal(name1, mname);
101 }
102
103 static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
104 {
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*/
109         if (p) {
110                 if (p[2] == '/') {
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;
116                 }
117         }
118         return NT_STATUS_OK;
119 }
120
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
128  lookup here.
129 ****************************************************************************/
130
131 static NTSTATUS check_parent_exists(TALLOC_CTX *ctx,
132                                 connection_struct *conn,
133                                 bool posix_pathnames,
134                                 const struct smb_filename *smb_fname,
135                                 char **pp_dirpath,
136                                 char **pp_start,
137                                 int *p_parent_stat_errno)
138 {
139         char *parent_name = NULL;
140         struct smb_filename *parent_fname = NULL;
141         const char *last_component = NULL;
142         NTSTATUS status;
143         int ret;
144
145         if (!parent_dirname(ctx, smb_fname->base_name,
146                                 &parent_name,
147                                 &last_component)) {
148                 return NT_STATUS_NO_MEMORY;
149         }
150
151         if (!posix_pathnames) {
152                 if (ms_has_wild(parent_name)) {
153                         goto no_optimization_out;
154                 }
155         }
156
157         /*
158          * If there was no parent component in
159          * smb_fname->base_name then don't do this
160          * optimization.
161          */
162         if (smb_fname->base_name == last_component) {
163                 goto no_optimization_out;
164         }
165
166         parent_fname = synthetic_smb_fname(ctx,
167                                            parent_name,
168                                            NULL,
169                                            NULL,
170                                            smb_fname->twrp,
171                                            smb_fname->flags);
172         if (parent_fname == NULL) {
173                 return NT_STATUS_NO_MEMORY;
174         }
175
176         ret = vfs_stat(conn, parent_fname);
177
178         /* If the parent stat failed, just continue
179            with the normal tree walk. */
180
181         if (ret == -1) {
182                 /*
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.
188                  */
189                 if (p_parent_stat_errno != NULL) {
190                         *p_parent_stat_errno = errno;
191                 }
192                 goto no_optimization_out;
193         }
194
195         status = check_for_dot_component(parent_fname);
196         if (!NT_STATUS_IS_OK(status)) {
197                 return status;
198         }
199
200         /* Parent exists - set "start" to be the
201          * last component to shorten the tree walk. */
202
203         /*
204          * Safe to use discard_const_p
205          * here as last_component points
206          * into our smb_fname->base_name.
207          */
208         *pp_start = discard_const_p(char, last_component);
209
210         /* Update dirpath. */
211         TALLOC_FREE(*pp_dirpath);
212         *pp_dirpath = talloc_strdup(ctx, parent_fname->base_name);
213         if (!*pp_dirpath) {
214                 return NT_STATUS_NO_MEMORY;
215         }
216
217         DEBUG(5,("check_parent_exists: name "
218                 "= %s, dirpath = %s, "
219                 "start = %s\n",
220                 smb_fname->base_name,
221                 *pp_dirpath,
222                 *pp_start));
223
224         return NT_STATUS_OK;
225
226   no_optimization_out:
227
228         /*
229          * We must still return an *pp_dirpath
230          * initialized to ".", and a *pp_start
231          * pointing at smb_fname->base_name.
232          */
233
234         TALLOC_FREE(parent_name);
235         TALLOC_FREE(parent_fname);
236
237         *pp_dirpath = talloc_strdup(ctx, ".");
238         if (*pp_dirpath == NULL) {
239                 return NT_STATUS_NO_MEMORY;
240         }
241         /*
242          * Safe to use discard_const_p
243          * here as by convention smb_fname->base_name
244          * is allocated off ctx.
245          */
246         *pp_start = discard_const_p(char, smb_fname->base_name);
247         return NT_STATUS_OK;
248 }
249
250 static bool find_snapshot_token(
251         const char *filename,
252         const char **_start,
253         const char **_next_component,
254         NTTIME *twrp)
255 {
256         const char *start = NULL;
257         const char *end = NULL;
258         struct tm tm;
259         time_t t;
260
261         start = strstr_m(filename, "@GMT-");
262
263         if (start == NULL) {
264                 return false;
265         }
266
267         if ((start > filename) && (start[-1] != '/')) {
268                 /* the GMT-token does not start a path-component */
269                 return false;
270         }
271
272         end = strptime(start, GMT_FORMAT, &tm);
273         if (end == NULL) {
274                 /* Not a valid timestring. */
275                 return false;
276         }
277
278         if ((end[0] != '\0') && (end[0] != '/')) {
279                 /*
280                  * It is not a complete path component, i.e. the path
281                  * component continues after the gmt-token.
282                  */
283                 return false;
284         }
285
286         tm.tm_isdst = -1;
287         t = timegm(&tm);
288         unix_to_nt_time(twrp, t);
289
290         DBG_DEBUG("Extracted @GMT-Timestamp %s\n",
291                   nt_time_string(talloc_tos(), *twrp));
292
293         *_start = start;
294
295         if (end[0] == '/') {
296                 end += 1;
297         }
298         *_next_component = end;
299
300         return true;
301 }
302
303 bool extract_snapshot_token(char *fname, NTTIME *twrp)
304 {
305         const char *start = NULL;
306         const char *next = NULL;
307         size_t remaining;
308         bool found;
309
310         found = find_snapshot_token(fname, &start, &next, twrp);
311         if (!found) {
312                 return false;
313         }
314
315         remaining = strlen(next);
316         memmove(discard_const_p(char, start), next, remaining+1);
317
318         return true;
319 }
320
321 /*
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.
325  *
326  * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
327  * at the *start* of a pathname component.
328  *
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.
332  *
333  */
334
335 NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
336                                     uint32_t ucf_flags,
337                                     NTTIME twrp)
338 {
339         bool found;
340
341         if (twrp != 0) {
342                 smb_fname->twrp = twrp;
343         }
344
345         if (!(ucf_flags & UCF_GMT_PATHNAME)) {
346                 return NT_STATUS_OK;
347         }
348
349         found = extract_snapshot_token(smb_fname->base_name, &twrp);
350         if (!found) {
351                 return NT_STATUS_OK;
352         }
353
354         if (smb_fname->twrp == 0) {
355                 smb_fname->twrp = twrp;
356         }
357
358         return NT_STATUS_OK;
359 }
360
361 static bool strnorm(char *s, int case_default)
362 {
363         if (case_default == CASE_UPPER)
364                 return strupper_m(s);
365         else
366                 return strlower_m(s);
367 }
368
369 /*
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.
373  */
374
375 static NTSTATUS normalize_filename_case(connection_struct *conn,
376                                         char *filename,
377                                         uint32_t ucf_flags)
378 {
379         bool ok;
380
381         if (ucf_flags & UCF_POSIX_PATHNAMES) {
382                 /*
383                  * POSIX never normalizes filename case.
384                  */
385                 return NT_STATUS_OK;
386         }
387         if (!conn->case_sensitive) {
388                 return NT_STATUS_OK;
389         }
390         if (conn->case_preserve) {
391                 return NT_STATUS_OK;
392         }
393         if (conn->short_case_preserve) {
394                 return NT_STATUS_OK;
395         }
396         ok = strnorm(filename, lp_default_case(SNUM(conn)));
397         if (!ok) {
398                 return NT_STATUS_INVALID_PARAMETER;
399         }
400         return NT_STATUS_OK;
401 }
402
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,
406 streams etc.
407
408 We assume that we have already done a chdir() to the right "root" directory
409 for this service.
410
411 Conversion to basic unix format is already done in check_path_syntax().
412
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().
415
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.
418
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.
422
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.
426
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
430 true for any file).
431 ****************************************************************************/
432
433 struct uc_state {
434         TALLOC_CTX *mem_ctx;
435         struct connection_struct *conn;
436         struct smb_filename *smb_fname;
437         const char *orig_path;
438         uint32_t ucf_flags;
439         char *name;
440         char *end;
441         char *dirpath;
442         char *stream;
443         bool component_was_mangled;
444         bool posix_pathnames;
445         bool done;
446         bool case_sensitive;
447         bool case_preserve;
448         bool short_case_preserve;
449 };
450
451 static NTSTATUS unix_convert_step_search_fail(
452         struct uc_state *state, NTSTATUS status)
453 {
454         char *unmangled;
455
456         if (state->end) {
457                 /*
458                  * An intermediate part of the name
459                  * can't be found.
460                  */
461                 DBG_DEBUG("Intermediate [%s] missing\n",
462                           state->name);
463                 *state->end = '/';
464
465                 /*
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
472                  * errors.
473                  */
474
475                 /*
476                  * ENOENT, ENOTDIR and ELOOP all map
477                  * to NT_STATUS_OBJECT_PATH_NOT_FOUND
478                  * in the filename walk.
479                  */
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;
484                 }
485                 return status;
486         }
487
488         /*
489          * ENOENT/EACCESS are the only valid errors
490          * here.
491          */
492
493         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
494                 if ((state->ucf_flags & UCF_PREP_CREATEFILE) == 0) {
495                         /*
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().
503                          */
504                         int ret;
505                         struct smb_filename dname = (struct smb_filename) {
506                                         .base_name = state->dirpath,
507                                         .twrp = state->smb_fname->twrp,
508                         };
509
510                         /* handle null paths */
511                         if ((dname.base_name == NULL) ||
512                                         (dname.base_name[0] == '\0')) {
513                                 return NT_STATUS_ACCESS_DENIED;
514                         }
515                         ret = SMB_VFS_LSTAT(state->conn, &dname);
516                         if (ret != 0) {
517                                 return NT_STATUS_ACCESS_DENIED;
518                         }
519                         if (!S_ISLNK(dname.st.st_ex_mode)) {
520                                 return NT_STATUS_ACCESS_DENIED;
521                         }
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;
526                         }
527                         return NT_STATUS_ACCESS_DENIED;
528                 } else {
529                         /*
530                          * This is the dropbox
531                          * behaviour. A dropbox is a
532                          * directory with only -wx
533                          * permissions, so
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.
539                          */
540                         status = NT_STATUS_OK;
541                 }
542         }
543
544         if (!NT_STATUS_IS_OK(status) &&
545             !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
546                 /*
547                  * ENOTDIR and ELOOP both map to
548                  * NT_STATUS_OBJECT_PATH_NOT_FOUND
549                  * in the filename walk.
550                  */
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;
554                 }
555                 return status;
556         }
557
558         /*
559          * POSIX pathnames must never call into mangling.
560          */
561         if (state->posix_pathnames) {
562                 goto done;
563         }
564
565         /*
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>.
571          */
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",
579                                   state->name);
580                         return NT_STATUS_INVALID_PARAMETER;
581                 }
582         }
583
584         /*
585          * check on the mangled stack to see if we can
586          * recover the base of the filename.
587          */
588
589         if (mangle_is_mangled(state->name, state->conn->params)
590             && mangle_lookup_name_from_8_3(state->mem_ctx,
591                                            state->name,
592                                            &unmangled,
593                                            state->conn->params)) {
594                 char *tmp;
595                 size_t name_ofs =
596                         state->name - state->smb_fname->base_name;
597
598                 if (!ISDOT(state->dirpath)) {
599                         tmp = talloc_asprintf(
600                                 state->smb_fname, "%s/%s",
601                                 state->dirpath, unmangled);
602                         TALLOC_FREE(unmangled);
603                 }
604                 else {
605                         tmp = unmangled;
606                 }
607                 if (tmp == NULL) {
608                         DBG_ERR("talloc failed\n");
609                         return NT_STATUS_NO_MEMORY;
610                 }
611                 TALLOC_FREE(state->smb_fname->base_name);
612                 state->smb_fname->base_name = tmp;
613                 state->name =
614                         state->smb_fname->base_name + name_ofs;
615                 state->end = state->name + strlen(state->name);
616         }
617
618   done:
619
620         DBG_DEBUG("New file [%s]\n", state->name);
621         state->done = true;
622         return NT_STATUS_OK;
623 }
624
625 static NTSTATUS unix_convert_step_stat(struct uc_state *state)
626 {
627         struct smb_filename dname;
628         char dot[2] = ".";
629         char *found_name = NULL;
630         int ret;
631         NTSTATUS status;
632
633         /*
634          * Check if the name exists up to this point.
635          */
636
637         DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state->smb_fname));
638
639         ret = vfs_stat(state->conn, state->smb_fname);
640         if (ret == 0) {
641                 /*
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.
644                  */
645                 if (state->end && !S_ISDIR(state->smb_fname->st.st_ex_mode)) {
646                         /*
647                          * An intermediate part of the name isn't
648                          * a directory.
649                          */
650                         DBG_DEBUG("Not a dir [%s]\n", state->name);
651                         *state->end = '/';
652                         /*
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
658                          * these two errors.
659                          */
660                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
661                 }
662                 return NT_STATUS_OK;
663         }
664
665         /* Stat failed - ensure we don't use it. */
666         SET_STAT_INVALID(state->smb_fname->st);
667
668         if (state->posix_pathnames) {
669                 /*
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
675                  * match on name foo.
676                  *
677                  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
678                  */
679                 if (state->end != NULL) {
680                         const char *morepath = NULL;
681                         /*
682                          * If this is intermediate we must
683                          * restore the full path.
684                          */
685                         *state->end = '/';
686                         /*
687                          * If there are any more components
688                          * after the failed LSTAT we cannot
689                          * continue.
690                          */
691                         morepath = strchr(state->end + 1, '/');
692                         if (morepath != NULL) {
693                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
694                         }
695                 }
696                 if (errno == ENOENT) {
697                         /* New file or directory. */
698                         state->done = true;
699                         return NT_STATUS_OK;
700                 }
701                 if ((errno == EACCES) &&
702                     (state->ucf_flags & UCF_PREP_CREATEFILE)) {
703                         /* POSIX Dropbox case. */
704                         errno = 0;
705                         state->done = true;
706                         return NT_STATUS_OK;
707                 }
708                 return map_nt_error_from_unix(errno);
709         }
710
711         /*
712          * Reset errno so we can detect
713          * directory open errors.
714          */
715         errno = 0;
716
717         /*
718          * Try to find this part of the path in the directory.
719          */
720
721         dname = (struct smb_filename) {
722                 .base_name = state->dirpath,
723                 .twrp = state->smb_fname->twrp,
724         };
725
726         /* handle null paths */
727         if ((dname.base_name == NULL) || (dname.base_name[0] == '\0')) {
728                 dname.base_name = dot;
729         }
730
731         status = get_real_filename(state->conn,
732                                    &dname,
733                                    state->name,
734                                    talloc_tos(),
735                                    &found_name);
736         if (!NT_STATUS_IS_OK(status)) {
737                 return unix_convert_step_search_fail(state, status);
738         }
739
740         /*
741          * Restore the rest of the string. If the string was
742          * mangled the size may have changed.
743          */
744         if (state->end) {
745                 char *tmp;
746                 size_t name_ofs =
747                         state->name - state->smb_fname->base_name;
748
749                 if (!ISDOT(state->dirpath)) {
750                         tmp = talloc_asprintf(state->smb_fname,
751                                               "%s/%s/%s", state->dirpath,
752                                               found_name, state->end+1);
753                 }
754                 else {
755                         tmp = talloc_asprintf(state->smb_fname,
756                                               "%s/%s", found_name,
757                                               state->end+1);
758                 }
759                 if (tmp == NULL) {
760                         DBG_ERR("talloc_asprintf failed\n");
761                         return NT_STATUS_NO_MEMORY;
762                 }
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);
767                 *state->end = '\0';
768         } else {
769                 char *tmp;
770                 size_t name_ofs =
771                         state->name - state->smb_fname->base_name;
772
773                 if (!ISDOT(state->dirpath)) {
774                         tmp = talloc_asprintf(state->smb_fname,
775                                               "%s/%s", state->dirpath,
776                                               found_name);
777                 } else {
778                         tmp = talloc_strdup(state->smb_fname,
779                                             found_name);
780                 }
781                 if (tmp == NULL) {
782                         DBG_ERR("talloc failed\n");
783                         return NT_STATUS_NO_MEMORY;
784                 }
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;
788
789                 /*
790                  * We just scanned for, and found the end of
791                  * the path. We must return a valid stat struct
792                  * if it exists. JRA.
793                  */
794
795                 ret = vfs_stat(state->conn, state->smb_fname);
796                 if (ret != 0) {
797                         SET_STAT_INVALID(state->smb_fname->st);
798                 }
799         }
800
801         TALLOC_FREE(found_name);
802         return NT_STATUS_OK;
803 }
804
805 static NTSTATUS unix_convert_step(struct uc_state *state)
806 {
807         NTSTATUS status;
808
809         /*
810          * Pinpoint the end of this section of the filename.
811          */
812         /* mb safe. '/' can't be in any encoded char. */
813         state->end = strchr(state->name, '/');
814
815         /*
816          * Chop the name at this point.
817          */
818         if (state->end != NULL) {
819                 *state->end = 0;
820         }
821
822         DBG_DEBUG("dirpath [%s] name [%s]\n", state->dirpath, state->name);
823
824         /* The name cannot have a component of "." */
825
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;
830                 }
831                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
832         }
833
834         status = unix_convert_step_stat(state);
835         if (!NT_STATUS_IS_OK(status)) {
836                 return status;
837         }
838         if (state->done) {
839                 return NT_STATUS_OK;
840         }
841
842         /*
843          * Add to the dirpath that we have resolved so far.
844          */
845
846         if (!ISDOT(state->dirpath)) {
847                 char *tmp = talloc_asprintf(state->mem_ctx,
848                                             "%s/%s", state->dirpath, state->name);
849                 if (!tmp) {
850                         DBG_ERR("talloc_asprintf failed\n");
851                         return NT_STATUS_NO_MEMORY;
852                 }
853                 TALLOC_FREE(state->dirpath);
854                 state->dirpath = tmp;
855         }
856         else {
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;
861                 }
862         }
863
864         /*
865          * Cache the dirpath thus far. Don't cache a name with mangled
866          * components as this can change the size.
867          */
868         if(!state->component_was_mangled) {
869                 stat_cache_add(state->orig_path,
870                                state->dirpath,
871                                state->smb_fname->twrp,
872                                state->case_sensitive);
873         }
874
875         /*
876          * Restore the / that we wiped out earlier.
877          */
878         if (state->end != NULL) {
879                 *state->end = '/';
880         }
881
882         return NT_STATUS_OK;
883 }
884
885 NTSTATUS unix_convert(TALLOC_CTX *mem_ctx,
886                       connection_struct *conn,
887                       const char *orig_path,
888                       NTTIME twrp,
889                       struct smb_filename **smb_fname_out,
890                       uint32_t ucf_flags)
891 {
892         struct uc_state uc_state;
893         struct uc_state *state = &uc_state;
894         NTSTATUS status;
895         int ret = -1;
896         int parent_stat_errno = 0;
897
898         *state = (struct uc_state) {
899                 .mem_ctx = mem_ctx,
900                 .conn = conn,
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,
907         };
908
909         *smb_fname_out = NULL;
910
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;
916         }
917
918         state->smb_fname = talloc_zero(state->mem_ctx, struct smb_filename);
919         if (state->smb_fname == NULL) {
920                 return NT_STATUS_NO_MEMORY;
921         }
922
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;
930                         goto err;
931                 }
932                 goto done;
933         }
934
935         state->smb_fname->flags = state->posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0;
936
937         DBG_DEBUG("Called on file [%s]\n", state->orig_path);
938
939         if (state->orig_path[0] == '/') {
940                 DBG_ERR("Path [%s] starts with '/'\n", state->orig_path);
941                 return NT_STATUS_OBJECT_NAME_INVALID;
942         }
943
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;
950                 goto err;
951         }
952
953         /* Canonicalize any @GMT- paths. */
954         status = canonicalize_snapshot_path(state->smb_fname, ucf_flags, twrp);
955         if (!NT_STATUS_IS_OK(status)) {
956                 goto err;
957         }
958
959         /*
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
963          * printing share.
964          * As we know this is valid we can return true here.
965          */
966
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;
971                         goto err;
972                 }
973                 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
974                         status = map_nt_error_from_unix(errno);
975                         goto err;
976                 }
977                 DBG_DEBUG("conversion finished [] -> [%s]\n",
978                           state->smb_fname->base_name);
979                 goto done;
980         }
981
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;
987                 } else {
988                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
989                 }
990                 goto err;
991         }
992
993         /*
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.
1000          */
1001
1002         status = normalize_filename_case(state->conn,
1003                                          state->smb_fname->base_name,
1004                                          ucf_flags);
1005         if (!NT_STATUS_IS_OK(status)) {
1006                 DBG_ERR("normalize_filename_case %s failed\n",
1007                                 state->smb_fname->base_name);
1008                 goto err;
1009         }
1010
1011         /*
1012          * Strip off the stream, and add it back when we're done with the
1013          * base_name.
1014          */
1015         if (!state->posix_pathnames) {
1016                 state->stream = strchr_m(state->smb_fname->base_name, ':');
1017
1018                 if (state->stream != NULL) {
1019                         char *tmp = talloc_strdup(state->smb_fname, state->stream);
1020                         if (tmp == NULL) {
1021                                 status = NT_STATUS_NO_MEMORY;
1022                                 goto err;
1023                         }
1024                         /*
1025                          * Since this is actually pointing into
1026                          * smb_fname->base_name this truncates base_name.
1027                          */
1028                         *state->stream = '\0';
1029                         state->stream = tmp;
1030
1031                         if (state->smb_fname->base_name[0] == '\0') {
1032                                 /*
1033                                  * orig_name was just a stream name.
1034                                  * This is a stream on the root of
1035                                  * the share. Replace base_name with
1036                                  * a "."
1037                                  */
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;
1042                                         goto err;
1043                                 }
1044                                 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
1045                                         status = map_nt_error_from_unix(errno);
1046                                         goto err;
1047                                 }
1048                                 /* dirpath must exist. */
1049                                 state->dirpath = talloc_strdup(state->mem_ctx,".");
1050                                 if (state->dirpath == NULL) {
1051                                         status = NT_STATUS_NO_MEMORY;
1052                                         goto err;
1053                                 }
1054                                 DBG_INFO("conversion finished [%s] -> [%s]\n",
1055                                          state->orig_path,
1056                                          state->smb_fname->base_name);
1057                                 goto done;
1058                         }
1059                 }
1060         }
1061
1062         state->name = state->smb_fname->base_name;
1063
1064         /*
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.
1069          *
1070          * Note: We're only checking base_name.  The stream_name will be
1071          * added and verified in build_stream_path().
1072          */
1073
1074         if (!state->case_sensitive ||
1075             !(state->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
1076         {
1077                 bool found;
1078
1079                 found = stat_cache_lookup(state->conn,
1080                                           &state->smb_fname->base_name,
1081                                           &state->dirpath,
1082                                           &state->name,
1083                                           state->smb_fname->twrp,
1084                                           &state->smb_fname->st);
1085                 /*
1086                  * stat_cache_lookup() allocates on talloc_tos() even
1087                  * when !found, reparent correctly
1088                  */
1089                 talloc_steal(state->smb_fname, state->smb_fname->base_name);
1090                 talloc_steal(state->mem_ctx, state->dirpath);
1091
1092                 if (found) {
1093                         goto done;
1094                 }
1095         }
1096
1097         /*
1098          * Make sure "dirpath" is an allocated string, we use this for
1099          * building the directories with talloc_asprintf and free it.
1100          */
1101
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;
1107                         goto err;
1108                 }
1109         }
1110
1111         /*
1112          * If we have a wildcard we must walk the path to
1113          * find where the error is, even if case sensitive
1114          * is true.
1115          */
1116
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;
1123                         goto fail;
1124                 }
1125         }
1126
1127         DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
1128                   state->smb_fname->base_name, state->dirpath, state->name);
1129
1130         /*
1131          * stat the name - if it exists then we can add the stream back (if
1132          * there was one) and be done!
1133          */
1134
1135         ret = vfs_stat(state->conn, state->smb_fname);
1136         if (ret == 0) {
1137                 status = check_for_dot_component(state->smb_fname);
1138                 if (!NT_STATUS_IS_OK(status)) {
1139                         goto fail;
1140                 }
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 "
1147                           "[%s] -> [%s]\n",
1148                           state->orig_path, state->smb_fname->base_name);
1149                 goto done;
1150         }
1151
1152         /* Stat failed - ensure we don't use it. */
1153         SET_STAT_INVALID(state->smb_fname->st);
1154
1155         /*
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.
1160          */
1161
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.
1166                 */
1167                 int saved_errno = errno;
1168                 status = check_parent_exists(state->mem_ctx,
1169                                         state->conn,
1170                                         state->posix_pathnames,
1171                                         state->smb_fname,
1172                                         &state->dirpath,
1173                                         &state->name,
1174                                         &parent_stat_errno);
1175                 errno = saved_errno;
1176                 if (!NT_STATUS_IS_OK(status)) {
1177                         goto fail;
1178                 }
1179         }
1180
1181         /*
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
1184          * won't help.
1185          *
1186          * NB. As POSIX sets state->case_sensitive as
1187          * true we will never call into mangle_is_mangled() here.
1188          */
1189
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)) {
1193
1194                 status = check_for_dot_component(state->smb_fname);
1195                 if (!NT_STATUS_IS_OK(status)) {
1196                         goto fail;
1197                 }
1198
1199                 /*
1200                  * The stat failed. Could be ok as it could be
1201                  * a new file.
1202                  */
1203
1204                 if (errno == ENOTDIR || errno == ELOOP) {
1205                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1206                         goto fail;
1207                 } else if (errno == ENOENT) {
1208                         /*
1209                          * Was it a missing last component ?
1210                          * or a missing intermediate component ?
1211                          *
1212                          * Optimization.
1213                          *
1214                          * For this code path we can guarantee that
1215                          * we have gone through check_parent_exists()
1216                          * and it returned NT_STATUS_OK.
1217                          *
1218                          * Either there was no parent component (".")
1219                          * parent_stat_errno == 0 and we have a missing
1220                          * last component here.
1221                          *
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.
1225                          *
1226                          * Either way we can avoid another STAT/LSTAT
1227                          * system call on the parent here.
1228                          */
1229                         if (parent_stat_errno == ENOTDIR ||
1230                                         parent_stat_errno == ENOENT ||
1231                                         parent_stat_errno == ELOOP) {
1232                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1233                                 goto fail;
1234                         }
1235
1236                         /*
1237                          * Missing last component is ok - new file.
1238                          * Also deal with permission denied elsewhere.
1239                          * Just drop out to done.
1240                          */
1241                         goto done;
1242                 }
1243         }
1244
1245         /*
1246          * is_mangled() was changed to look at an entire pathname, not
1247          * just a component. JRA.
1248          */
1249
1250         if (state->posix_pathnames) {
1251                 /*
1252                  * POSIX names are never mangled and we must not
1253                  * call into mangling functions.
1254                  */
1255                 state->component_was_mangled = false;
1256         } else if (mangle_is_mangled(state->name, state->conn->params)) {
1257                 state->component_was_mangled = true;
1258         }
1259
1260         /*
1261          * Now we need to recursively match the name against the real
1262          * directory structure.
1263          */
1264
1265         /*
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.
1268          */
1269
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)) {
1274                                 goto err;
1275                         }
1276                         goto fail;
1277                 }
1278                 if (state->done) {
1279                         goto done;
1280                 }
1281         }
1282
1283         /*
1284          * Cache the full path. Don't cache a name with mangled or wildcard
1285          * components as this can change the size.
1286          */
1287
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);
1293         }
1294
1295         /*
1296          * The name has been resolved.
1297          */
1298
1299  done:
1300         /* Add back the stream if one was stripped off originally. */
1301         if (state->stream != NULL) {
1302                 state->smb_fname->stream_name = state->stream;
1303
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)) {
1307                         goto fail;
1308                 }
1309         }
1310
1311         DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
1312                    state->orig_path, smb_fname_str_dbg(state->smb_fname));
1313
1314         TALLOC_FREE(state->dirpath);
1315         *smb_fname_out = state->smb_fname;
1316         return NT_STATUS_OK;
1317  fail:
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(
1322                         state->smb_fname,
1323                         "%s/%s",
1324                         state->dirpath,
1325                         state->name);
1326         } else {
1327                 state->smb_fname->base_name = talloc_strdup(
1328                         state->smb_fname, state->name);
1329         }
1330         if (state->smb_fname->base_name == NULL) {
1331                 DBG_ERR("talloc_asprintf failed\n");
1332                 status = NT_STATUS_NO_MEMORY;
1333                 goto err;
1334         }
1335
1336         *smb_fname_out = state->smb_fname;
1337         TALLOC_FREE(state->dirpath);
1338         return status;
1339  err:
1340         TALLOC_FREE(state->smb_fname);
1341         return status;
1342 }
1343
1344 /****************************************************************************
1345  Ensure a path is not vetoed.
1346 ****************************************************************************/
1347
1348 static NTSTATUS check_veto_path(connection_struct *conn,
1349                         const struct smb_filename *smb_fname)
1350 {
1351         const char *name = smb_fname->base_name;
1352
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",
1357                                                 name));
1358                         return map_nt_error_from_unix(ENOENT);
1359                 }
1360         }
1361         return NT_STATUS_OK;
1362 }
1363
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 ****************************************************************************/
1370
1371 static NTSTATUS check_name(connection_struct *conn,
1372                         const struct smb_filename *smb_fname)
1373 {
1374         NTSTATUS status = check_veto_path(conn, smb_fname);
1375
1376         if (!NT_STATUS_IS_OK(status)) {
1377                 return status;
1378         }
1379
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)));
1386                         return status;
1387                 }
1388         }
1389
1390         return NT_STATUS_OK;
1391 }
1392
1393 /****************************************************************************
1394  Check if two filenames are equal.
1395  This needs to be careful about whether we are case sensitive.
1396 ****************************************************************************/
1397
1398 static bool fname_equal(const char *name1, const char *name2,
1399                 bool case_sensitive)
1400 {
1401         /* Normal filename handling */
1402         if (case_sensitive) {
1403                 return(strcmp(name1,name2) == 0);
1404         }
1405
1406         return(strequal(name1,name2));
1407 }
1408
1409 static bool sname_equal(const char *name1, const char *name2,
1410                 bool case_sensitive)
1411 {
1412         bool match;
1413         const char *s1 = NULL;
1414         const char *s2 = NULL;
1415         size_t n1;
1416         size_t n2;
1417         const char *e1 = NULL;
1418         const char *e2 = NULL;
1419         char *c1 = NULL;
1420         char *c2 = NULL;
1421
1422         match = fname_equal(name1, name2, case_sensitive);
1423         if (match) {
1424                 return true;
1425         }
1426
1427         if (name1[0] != ':') {
1428                 return false;
1429         }
1430         if (name2[0] != ':') {
1431                 return false;
1432         }
1433         s1 = &name1[1];
1434         e1 = strchr(s1, ':');
1435         if (e1 == NULL) {
1436                 n1 = strlen(s1);
1437         } else {
1438                 n1 = PTR_DIFF(e1, s1);
1439         }
1440         s2 = &name2[1];
1441         e2 = strchr(s2, ':');
1442         if (e2 == NULL) {
1443                 n2 = strlen(s2);
1444         } else {
1445                 n2 = PTR_DIFF(e2, s2);
1446         }
1447
1448         /* Normal filename handling */
1449         if (case_sensitive) {
1450                 return (strncmp(s1, s2, n1) == 0);
1451         }
1452
1453         /*
1454          * We can't use strnequal() here
1455          * as it takes the number of codepoints
1456          * and not the number of bytes.
1457          *
1458          * So we make a copy before calling
1459          * strequal().
1460          *
1461          * Note that we TALLOC_FREE() in reverse order
1462          * in order to avoid memory fragmentation.
1463          */
1464
1465         c1 = talloc_strndup(talloc_tos(), s1, n1);
1466         c2 = talloc_strndup(talloc_tos(), s2, n2);
1467         if (c1 == NULL || c2 == NULL) {
1468                 TALLOC_FREE(c2);
1469                 TALLOC_FREE(c1);
1470                 return (strncmp(s1, s2, n1) == 0);
1471         }
1472
1473         match = strequal(c1, c2);
1474         TALLOC_FREE(c2);
1475         TALLOC_FREE(c1);
1476         return match;
1477 }
1478
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 ****************************************************************************/
1483
1484 NTSTATUS get_real_filename_full_scan_at(struct files_struct *dirfsp,
1485                                         const char *name,
1486                                         bool mangled,
1487                                         TALLOC_CTX *mem_ctx,
1488                                         char **found_name)
1489 {
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;
1495         long curpos;
1496         NTSTATUS status;
1497
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.
1501          */
1502         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
1503                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1504         }
1505
1506         /*
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.
1511          * (JRA).
1512          *
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.
1519          */
1520
1521         if (mangled && !conn->case_sensitive) {
1522                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
1523                                                        &unmangled_name,
1524                                                        conn->params);
1525                 if (!mangled) {
1526                         /* Name is now unmangled. */
1527                         name = unmangled_name;
1528                 }
1529         }
1530
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),
1536                            nt_errstr(status));
1537                 TALLOC_FREE(unmangled_name);
1538                 return status;
1539         }
1540
1541         /* now scan for matching names */
1542         curpos = 0;
1543         while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
1544
1545                 /* Is it dot or dot dot. */
1546                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1547                         TALLOC_FREE(talloced);
1548                         continue;
1549                 }
1550
1551                 /*
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.
1555                  */
1556
1557                 /*
1558                  * Check mangled name against mangled name, or unmangled name
1559                  * against unmangled name.
1560                  */
1561
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);
1568                         if (!*found_name) {
1569                                 TALLOC_FREE(talloced);
1570                                 return NT_STATUS_NO_MEMORY;
1571                         }
1572                         TALLOC_FREE(talloced);
1573                         return NT_STATUS_OK;
1574                 }
1575                 TALLOC_FREE(talloced);
1576         }
1577
1578         TALLOC_FREE(unmangled_name);
1579         TALLOC_FREE(cur_dir);
1580         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1581 }
1582
1583 NTSTATUS get_real_filename_full_scan(connection_struct *conn,
1584                                      const char *path,
1585                                      const char *name,
1586                                      bool mangled,
1587                                      TALLOC_CTX *mem_ctx,
1588                                      char **found_name)
1589 {
1590         struct smb_filename *smb_dname = NULL;
1591         NTSTATUS status;
1592
1593         /* handle null paths */
1594         if ((path == NULL) || (*path == 0)) {
1595                 path = ".";
1596         }
1597
1598         status = synthetic_pathref(
1599                 talloc_tos(),
1600                 conn->cwd_fsp,
1601                 path,
1602                 NULL,
1603                 NULL,
1604                 0,
1605                 0,
1606                 &smb_dname);
1607         if (!NT_STATUS_IS_OK(status)) {
1608                 return status;
1609         }
1610
1611         status = get_real_filename_full_scan_at(
1612                 smb_dname->fsp, name, mangled, mem_ctx, found_name);
1613
1614         TALLOC_FREE(smb_dname);
1615         return status;
1616 }
1617
1618 /****************************************************************************
1619  Wrapper around the vfs get_real_filename and the full directory scan
1620  fallback.
1621 ****************************************************************************/
1622
1623 NTSTATUS get_real_filename_at(struct files_struct *dirfsp,
1624                               const char *name,
1625                               TALLOC_CTX *mem_ctx,
1626                               char **found_name)
1627 {
1628         struct connection_struct *conn = dirfsp->conn;
1629         NTSTATUS status;
1630         bool mangled;
1631
1632         mangled = mangle_is_mangled(name, conn->params);
1633
1634         if (mangled) {
1635                 status = get_real_filename_full_scan_at(
1636                         dirfsp, name, mangled, mem_ctx, found_name);
1637                 return status;
1638         }
1639
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);
1643
1644         /*
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.
1648          */
1649         if (NT_STATUS_IS_OK(status) ||
1650             !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1651                 return status;
1652         }
1653
1654         status = get_real_filename_full_scan_at(
1655                 dirfsp, name, mangled, mem_ctx, found_name);
1656         return status;
1657 }
1658
1659 /*
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().
1667  */
1668 static bool get_real_filename_cache_key(
1669         TALLOC_CTX *mem_ctx,
1670         struct files_struct *dirfsp,
1671         const char *name,
1672         DATA_BLOB *_key)
1673 {
1674         struct file_id fid = vfs_file_id_from_sbuf(
1675                 dirfsp->conn, &dirfsp->fsp_name->st);
1676         char *upper = NULL;
1677         uint8_t *key = NULL;
1678         size_t namelen, keylen;
1679
1680         upper = talloc_strdup_upper(mem_ctx, name);
1681         if (upper == NULL) {
1682                 return false;
1683         }
1684         namelen = talloc_get_size(upper);
1685
1686         keylen = namelen + sizeof(fid);
1687         if (keylen < sizeof(fid)) {
1688                 TALLOC_FREE(upper);
1689                 return false;
1690         }
1691
1692         key = talloc_size(mem_ctx, keylen);
1693         if (key == NULL) {
1694                 TALLOC_FREE(upper);
1695                 return false;
1696         }
1697
1698         memcpy(key, &fid, sizeof(fid));
1699         memcpy(key + sizeof(fid), upper, namelen);
1700         TALLOC_FREE(upper);
1701
1702         *_key = (DATA_BLOB) { .data = key, .length = keylen, };
1703         return true;
1704 }
1705
1706 static NTSTATUS get_real_filename(connection_struct *conn,
1707                                   struct smb_filename *path,
1708                                   const char *name,
1709                                   TALLOC_CTX *mem_ctx,
1710                                   char **found_name)
1711 {
1712         struct smb_filename *smb_dname = NULL;
1713         NTSTATUS status;
1714
1715         smb_dname = cp_smb_filename_nostream(talloc_tos(), path);
1716         if (smb_dname == NULL) {
1717                 return NT_STATUS_NO_MEMORY;
1718         }
1719
1720 again:
1721         status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
1722
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;
1726         }
1727
1728         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
1729             (smb_dname->twrp != 0)) {
1730                 /*
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
1737                  * bad.
1738                  */
1739                 smb_dname->twrp = 0;
1740                 goto again;
1741         }
1742
1743         if (!NT_STATUS_IS_OK(status)) {
1744                 DBG_DEBUG("openat_pathref_fsp(%s) failed: %s\n",
1745                           smb_fname_str_dbg(smb_dname),
1746                           nt_errstr(status));
1747
1748                 /*
1749                  * ENOTDIR and ELOOP both map to
1750                  * NT_STATUS_OBJECT_PATH_NOT_FOUND in the filename
1751                  * walk.
1752                  */
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;
1756                 }
1757
1758                 return status;
1759         }
1760
1761         status = get_real_filename_at(
1762                 smb_dname->fsp, name, mem_ctx, found_name);
1763         TALLOC_FREE(smb_dname);
1764         return status;
1765 }
1766
1767 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1768                                   connection_struct *conn,
1769                                   struct smb_filename *smb_fname)
1770 {
1771         NTSTATUS status;
1772         unsigned int i, num_streams = 0;
1773         struct stream_struct *streams = NULL;
1774         struct smb_filename *pathref = NULL;
1775
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;
1779         }
1780
1781         if (errno != ENOENT) {
1782                 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1783                 status = map_nt_error_from_unix(errno);
1784                 goto fail;
1785         }
1786
1787         if (smb_fname->fsp == NULL) {
1788                 status = synthetic_pathref(mem_ctx,
1789                                         conn->cwd_fsp,
1790                                         smb_fname->base_name,
1791                                         NULL,
1792                                         NULL,
1793                                         smb_fname->twrp,
1794                                         smb_fname->flags,
1795                                         &pathref);
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;
1802                         }
1803                         DBG_DEBUG("synthetic_pathref failed: %s\n",
1804                                   nt_errstr(status));
1805                         goto fail;
1806                 }
1807         } else {
1808                 pathref = smb_fname;
1809         }
1810
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;
1818         }
1819
1820         if (!NT_STATUS_IS_OK(status)) {
1821                 DEBUG(10, ("vfs_fstreaminfo failed: %s\n", nt_errstr(status)));
1822                 goto fail;
1823         }
1824
1825         for (i=0; i<num_streams; i++) {
1826                 bool equal = sname_equal(
1827                         smb_fname->stream_name,
1828                         streams[i].name,
1829                         conn->case_sensitive);
1830
1831                 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
1832                           smb_fname->stream_name,
1833                           streams[i].name,
1834                           equal ? "" : "not ");
1835
1836                 if (equal) {
1837                         break;
1838                 }
1839         }
1840
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;
1847         }
1848
1849         DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1850                 smb_fname->stream_name, streams[i].name));
1851
1852
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;
1857                 goto fail;
1858         }
1859
1860         SET_STAT_INVALID(smb_fname->st);
1861
1862         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1863                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1864         }
1865         status = NT_STATUS_OK;
1866  fail:
1867         TALLOC_FREE(pathref);
1868         TALLOC_FREE(streams);
1869         return status;
1870 }
1871
1872 /*
1873  * Lightweight function to just get last component
1874  * for rename / enumerate directory calls.
1875  */
1876
1877 char *get_original_lcomp(TALLOC_CTX *ctx,
1878                         connection_struct *conn,
1879                         const char *filename_in,
1880                         uint32_t ucf_flags)
1881 {
1882         char *last_slash = NULL;
1883         char *orig_lcomp;
1884         NTSTATUS status;
1885
1886         last_slash = strrchr(filename_in, '/');
1887         if (last_slash != NULL) {
1888                 orig_lcomp = talloc_strdup(ctx, last_slash+1);
1889         } else {
1890                 orig_lcomp = talloc_strdup(ctx, filename_in);
1891         }
1892         if (orig_lcomp == NULL) {
1893                 return NULL;
1894         }
1895         status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 TALLOC_FREE(orig_lcomp);
1898                 return NULL;
1899         }
1900         return orig_lcomp;
1901 }
1902
1903 /*
1904  * Deal with the SMB1 semantics of sending a pathname with a
1905  * wildcard as the terminal component for a SMB1search or
1906  * trans2 findfirst.
1907  */
1908
1909 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
1910                                            connection_struct *conn,
1911                                            char *name_in,
1912                                            uint32_t ucf_flags,
1913                                            struct files_struct **_dirfsp,
1914                                            struct smb_filename **_smb_fname_out,
1915                                            char **_mask_out)
1916 {
1917         NTSTATUS status;
1918         char *p = NULL;
1919         char *mask = NULL;
1920         struct smb_filename *smb_fname = NULL;
1921         NTTIME twrp = 0;
1922
1923         *_smb_fname_out = NULL;
1924         *_dirfsp = NULL;
1925         *_mask_out = NULL;
1926
1927         DBG_DEBUG("name_in: %s\n", name_in);
1928
1929         if (ucf_flags & UCF_GMT_PATHNAME) {
1930                 extract_snapshot_token(name_in, &twrp);
1931                 ucf_flags &= ~UCF_GMT_PATHNAME;
1932         }
1933
1934         if (ucf_flags & UCF_DFS_PATHNAME) {
1935                 /*
1936                  * We've been given a raw DFS pathname.
1937                  */
1938                 char *pathname = NULL;
1939                 DBG_DEBUG("Before dfs_filename_convert name_in: %s\n", name_in);
1940                 status = dfs_filename_convert(ctx,
1941                                               conn,
1942                                               ucf_flags,
1943                                               name_in,
1944                                               &pathname);
1945                 if (!NT_STATUS_IS_OK(status)) {
1946                         DBG_DEBUG("dfs_filename_convert "
1947                                 "failed for name %s with %s\n",
1948                                 name_in,
1949                                 nt_errstr(status));
1950                         return status;
1951                 }
1952                 ucf_flags &= ~UCF_DFS_PATHNAME;
1953                 name_in = pathname;
1954                 DBG_DEBUG("After dfs_filename_convert name_in: %s\n", name_in);
1955         }
1956
1957         /* Get the original lcomp. */
1958         mask = get_original_lcomp(ctx,
1959                                   conn,
1960                                   name_in,
1961                                   ucf_flags);
1962         if (mask == NULL) {
1963                 return NT_STATUS_NO_MEMORY;
1964         }
1965
1966         if (mask[0] == '\0') {
1967                 /* Windows and OS/2 systems treat search on the root as * */
1968                 TALLOC_FREE(mask);
1969                 mask = talloc_strdup(ctx, "*");
1970                 if (mask == NULL) {
1971                         return NT_STATUS_NO_MEMORY;
1972                 }
1973         }
1974
1975         DBG_DEBUG("mask = %s\n", mask);
1976
1977         /*
1978          * Remove the terminal component so
1979          * filename_convert_dirfsp never sees the mask.
1980          */
1981         p = strrchr_m(name_in,'/');
1982         if (p == NULL) {
1983                 /* filename_convert_dirfsp handles a '\0' name. */
1984                 name_in[0] = '\0';
1985         } else {
1986                 *p = '\0';
1987         }
1988
1989         DBG_DEBUG("For filename_convert_dirfsp: name_in = %s\n",
1990                 name_in);
1991
1992         /* Convert the parent directory path. */
1993         status = filename_convert_dirfsp(ctx,
1994                                          conn,
1995                                          name_in,
1996                                          ucf_flags,
1997                                          twrp,
1998                                          _dirfsp,
1999                                          &smb_fname);
2000
2001         if (!NT_STATUS_IS_OK(status)) {
2002                 DBG_DEBUG("filename_convert error for %s: %s\n",
2003                         name_in,
2004                         nt_errstr(status));
2005         }
2006
2007         *_smb_fname_out = talloc_move(ctx, &smb_fname);
2008         *_mask_out = talloc_move(ctx, &mask);
2009
2010         return status;
2011 }
2012
2013 /*
2014  * Get the correct capitalized stream name hanging off
2015  * base_fsp. Equivalent of get_real_filename(), but for streams.
2016  */
2017 static NTSTATUS get_real_stream_name(
2018         TALLOC_CTX *mem_ctx,
2019         struct files_struct *base_fsp,
2020         const char *stream_name,
2021         char **_found)
2022 {
2023         unsigned int i, num_streams = 0;
2024         struct stream_struct *streams = NULL;
2025         NTSTATUS status;
2026
2027         status = vfs_fstreaminfo(
2028                 base_fsp, talloc_tos(), &num_streams, &streams);
2029         if (!NT_STATUS_IS_OK(status)) {
2030                 return status;
2031         }
2032
2033         for (i=0; i<num_streams; i++) {
2034                 bool equal = sname_equal(stream_name, streams[i].name, false);
2035
2036                 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
2037                           stream_name,
2038                           streams[i].name,
2039                           equal ? "" : "not ");
2040
2041                 if (equal) {
2042                         *_found = talloc_move(mem_ctx, &streams[i].name);
2043                         TALLOC_FREE(streams);
2044                         return NT_STATUS_OK;
2045                 }
2046         }
2047
2048         TALLOC_FREE(streams);
2049         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2050 }
2051
2052 static bool filename_split_lcomp(
2053         TALLOC_CTX *mem_ctx,
2054         const char *name_in,
2055         bool posix,
2056         char **_dirname,
2057         const char **_fname_rel,
2058         const char **_streamname)
2059 {
2060         const char *lcomp = NULL;
2061         const char *fname_rel = NULL;
2062         const char *streamname = NULL;
2063         char *dirname = NULL;
2064
2065         if (name_in[0] == '\0') {
2066                 fname_rel = ".";
2067                 dirname = talloc_strdup(mem_ctx, "");
2068                 if (dirname == NULL) {
2069                         return false;
2070                 }
2071                 goto done;
2072         }
2073
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) {
2079                         return false;
2080                 }
2081                 goto find_stream;
2082         }
2083
2084         /*
2085          * No slash, dir is emtpy
2086          */
2087         dirname = talloc_strdup(mem_ctx, "");
2088         if (dirname == NULL) {
2089                 return false;
2090         }
2091
2092         if (!posix && (name_in[0] == ':')) {
2093                 /*
2094                  * Special case for stream on root directory
2095                  */
2096                 fname_rel = ".";
2097                 streamname = name_in;
2098                 goto done;
2099         }
2100
2101         fname_rel = name_in;
2102
2103 find_stream:
2104         if (!posix) {
2105                 streamname = strchr_m(fname_rel, ':');
2106
2107                 if (streamname != NULL) {
2108                         fname_rel = talloc_strndup(
2109                                 mem_ctx,
2110                                 fname_rel,
2111                                 streamname - fname_rel);
2112                         if (fname_rel == NULL) {
2113                                 TALLOC_FREE(dirname);
2114                                 return false;
2115                         }
2116                 }
2117         }
2118
2119 done:
2120         *_dirname = dirname;
2121         *_fname_rel = fname_rel;
2122         *_streamname = streamname;
2123         return true;
2124 }
2125
2126 /*
2127  * Create the correct capitalization of a file name to be created.
2128  */
2129 static NTSTATUS filename_convert_normalize_new(
2130         TALLOC_CTX *mem_ctx,
2131         struct connection_struct *conn,
2132         char *name_in,
2133         char **_normalized)
2134 {
2135         char *name = name_in;
2136
2137         *_normalized = NULL;
2138
2139         if (!conn->case_preserve ||
2140             (mangle_is_8_3(name, false,
2141                            conn->params) &&
2142              !conn->short_case_preserve)) {
2143
2144                 char *normalized = talloc_strdup(mem_ctx, name);
2145                 if (normalized == NULL) {
2146                         return NT_STATUS_NO_MEMORY;
2147                 }
2148
2149                 strnorm(normalized, lp_default_case(SNUM(conn)));
2150                 name = normalized;
2151         }
2152
2153         if (mangle_is_mangled(name, conn->params)) {
2154                 bool found;
2155                 char *unmangled = NULL;
2156
2157                 found = mangle_lookup_name_from_8_3(
2158                         mem_ctx, name, &unmangled, conn->params);
2159                 if (found) {
2160                         name = unmangled;
2161                 }
2162         }
2163
2164         if (name != name_in) {
2165                 *_normalized = name;
2166         }
2167
2168         return NT_STATUS_OK;
2169 }
2170
2171 /*
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
2175  * ENOENT.
2176  */
2177 static NTSTATUS openat_pathref_fsp_case_insensitive(
2178         struct files_struct *dirfsp,
2179         struct smb_filename *smb_fname_rel,
2180         uint32_t ucf_flags)
2181 {
2182         const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2183         DATA_BLOB cache_key = { .data = NULL, };
2184         char *found_name = NULL;
2185         NTSTATUS status;
2186         bool ok;
2187
2188         SET_STAT_INVALID(smb_fname_rel->st);
2189
2190         status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2191
2192         if (NT_STATUS_IS_OK(status)) {
2193                 return NT_STATUS_OK;
2194         }
2195
2196         if (VALID_STAT(smb_fname_rel->st)) {
2197                 /*
2198                  * We got an error although the object existed. Might
2199                  * be a symlink we don't want.
2200                  */
2201                 return status;
2202         }
2203
2204         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2205                 /*
2206                  * Only retry on ENOENT
2207                  */
2208                 return status;
2209         }
2210
2211         if (posix || dirfsp->conn->case_sensitive) {
2212                 /*
2213                  * Only return case insensitive if required
2214                  */
2215                 return status;
2216         }
2217
2218         if (lp_stat_cache()) {
2219                 char *base_name = smb_fname_rel->base_name;
2220                 DATA_BLOB value = { .data = NULL };
2221
2222                 ok = get_real_filename_cache_key(
2223                         talloc_tos(), dirfsp, base_name, &cache_key);
2224                 if (!ok) {
2225                         /*
2226                          * probably ENOMEM, just bail
2227                          */
2228                         return status;
2229                 }
2230
2231                 DO_PROFILE_INC(statcache_lookups);
2232
2233                 ok = memcache_lookup(
2234                         NULL, GETREALFILENAME_CACHE, cache_key, &value);
2235                 if (!ok) {
2236                         DO_PROFILE_INC(statcache_misses);
2237                         goto lookup;
2238                 }
2239                 DO_PROFILE_INC(statcache_hits);
2240
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;
2247                 }
2248
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;
2253                 }
2254
2255                 memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
2256         }
2257
2258 lookup:
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)) {
2263                 /*
2264                  * dropbox
2265                  */
2266                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2267         }
2268
2269         if (NT_STATUS_IS_OK(status)) {
2270                 TALLOC_FREE(smb_fname_rel->base_name);
2271                 smb_fname_rel->base_name = found_name;
2272
2273                 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2274         }
2275
2276         if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
2277                 DATA_BLOB value = {
2278                         .data = (uint8_t *)smb_fname_rel->base_name,
2279                         .length = strlen(smb_fname_rel->base_name) + 1,
2280                 };
2281
2282                 memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
2283         }
2284
2285         TALLOC_FREE(cache_key.data);
2286
2287         return status;
2288 }
2289
2290 /*
2291  * Split up name_in as sent by the client into a directory pathref fsp
2292  * and a relative smb_filename.
2293  */
2294 static const char *previous_slash(const char *name_in, const char *slash)
2295 {
2296         const char *prev = name_in;
2297
2298         while (true) {
2299                 const char *next = strchr_m(prev, '/');
2300
2301                 SMB_ASSERT(next != NULL); /* we have at least one slash */
2302
2303                 if (next == slash) {
2304                         break;
2305                 }
2306
2307                 prev = next+1;
2308         };
2309
2310         if (prev == name_in) {
2311                 /* no previous slash */
2312                 return NULL;
2313         }
2314
2315         return prev;
2316 }
2317
2318 static char *symlink_target_path(
2319         TALLOC_CTX *mem_ctx,
2320         const char *name_in,
2321         const char *substitute,
2322         size_t unparsed)
2323 {
2324         size_t name_in_len = strlen(name_in);
2325         const char *p_unparsed = NULL;
2326         const char *parent = NULL;
2327         char *ret;
2328
2329         SMB_ASSERT(unparsed <= name_in_len);
2330
2331         p_unparsed = name_in + (name_in_len - unparsed);
2332
2333         if (substitute[0] == '/') {
2334                 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
2335                 return ret;
2336         }
2337
2338         if (unparsed == 0) {
2339                 parent = strrchr_m(name_in, '/');
2340         } else {
2341                 parent = previous_slash(name_in, p_unparsed);
2342         }
2343
2344         if (parent == NULL) {
2345                 /* no previous slash */
2346                 parent = name_in;
2347         }
2348
2349         ret = talloc_asprintf(
2350                 mem_ctx,
2351                 "%.*s%s%s",
2352                 (int)(parent - name_in),
2353                 name_in,
2354                 substitute,
2355                 p_unparsed);
2356         return ret;
2357 }
2358
2359 /*
2360  * Split up name_in as sent by the client into a directory pathref fsp
2361  * and a relative smb_filename.
2362  */
2363 static NTSTATUS filename_convert_dirfsp_nosymlink(
2364         TALLOC_CTX *mem_ctx,
2365         connection_struct *conn,
2366         const char *name_in,
2367         uint32_t ucf_flags,
2368         NTTIME twrp,
2369         struct files_struct **_dirfsp,
2370         struct smb_filename **_smb_fname,
2371         char **_substitute,
2372         size_t *_unparsed)
2373 {
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;
2383         bool ok;
2384         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2385
2386         if (ucf_flags & UCF_DFS_PATHNAME) {
2387                 char *fname = NULL;
2388                 NTTIME dfs_twrp = 0;
2389                 status = dfs_redirect(
2390                         mem_ctx,
2391                         conn,
2392                         name_in,
2393                         ucf_flags,
2394                         !conn->sconn->using_smb2,
2395                         &dfs_twrp,
2396                         &fname);
2397                 if (!NT_STATUS_IS_OK(status)) {
2398                         DBG_DEBUG("dfs_redirect "
2399                                 "failed for name %s with %s\n",
2400                                 name_in,
2401                                 nt_errstr(status));
2402                         return status;
2403                 }
2404                 name_in = fname;
2405                 ucf_flags &= ~UCF_DFS_PATHNAME;
2406                 if (twrp == 0 && dfs_twrp != 0) {
2407                         twrp = dfs_twrp;
2408                 }
2409         }
2410
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;
2415                 }
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};
2425
2426                 *_dirfsp = conn->cwd_fsp;
2427                 *_smb_fname = smb_fname;
2428                 return NT_STATUS_OK;
2429         }
2430
2431         /*
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
2437          * the client.
2438          */
2439         if (ISDOT(name_in)) {
2440                 status = NT_STATUS_OBJECT_NAME_INVALID;
2441                 goto fail;
2442         }
2443
2444         ok = filename_split_lcomp(
2445                 talloc_tos(),
2446                 name_in,
2447                 posix,
2448                 &dirname,
2449                 &fname_rel,
2450                 &streamname);
2451         if (!ok) {
2452                 status = NT_STATUS_NO_MEMORY;
2453                 goto fail;
2454         }
2455
2456         if (!posix) {
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;
2461                         goto fail;
2462                 }
2463         }
2464
2465         if (dirname[0] == '\0') {
2466                 status = synthetic_pathref(
2467                         mem_ctx,
2468                         conn->cwd_fsp,
2469                         ".",
2470                         NULL,
2471                         NULL,
2472                         0,
2473                         posix ? SMB_FILENAME_POSIX_PATH : 0,
2474                         &smb_dirname);
2475         } else {
2476                 char *substitute = NULL;
2477                 size_t unparsed = 0;
2478
2479                 status = openat_pathref_dirfsp_nosymlink(
2480                         mem_ctx,
2481                         conn,
2482                         dirname,
2483                         0,
2484                         &smb_dirname,
2485                         &unparsed,
2486                         &substitute);
2487
2488                 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
2489
2490                         size_t name_in_len = strlen(name_in);
2491                         size_t dirname_len = strlen(dirname);
2492
2493                         SMB_ASSERT(name_in_len >= dirname_len);
2494
2495                         *_substitute = substitute;
2496                         *_unparsed = unparsed + (name_in_len - dirname_len);
2497
2498                         goto fail;
2499                 }
2500         }
2501
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 DBG_DEBUG("opening directory %s failed: %s\n",
2504                           dirname,
2505                           nt_errstr(status));
2506                 TALLOC_FREE(dirname);
2507
2508                 if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
2509                         /* MS-DFS error must propagate back out. */
2510                         goto fail;
2511                 }
2512
2513                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2514                         /*
2515                          * Except ACCESS_DENIED, everything else leads
2516                          * to PATH_NOT_FOUND.
2517                          */
2518                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2519                 }
2520
2521                 goto fail;
2522         }
2523
2524         if (!VALID_STAT_OF_DIR(smb_dirname->st)) {
2525                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2526                 goto fail;
2527         }
2528
2529         /*
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.
2535          */
2536
2537         /* Relative filename can't be empty */
2538         if (fname_rel[0] == '\0') {
2539                 status = NT_STATUS_OBJECT_NAME_INVALID;
2540                 goto fail;
2541         }
2542
2543         /* Relative filename can't be ".." */
2544         if (ISDOTDOT(fname_rel)) {
2545                 status = NT_STATUS_OBJECT_NAME_INVALID;
2546                 goto fail;
2547         }
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;
2551                 goto fail;
2552         }
2553
2554         TALLOC_FREE(dirname);
2555
2556         smb_fname_rel = synthetic_smb_fname(
2557                 mem_ctx,
2558                 fname_rel,
2559                 streamname,
2560                 NULL,
2561                 twrp,
2562                 posix ? SMB_FILENAME_POSIX_PATH : 0);
2563         if (smb_fname_rel == NULL) {
2564                 status = NT_STATUS_NO_MEMORY;
2565                 goto fail;
2566         }
2567
2568         if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
2569             is_named_stream(smb_fname_rel)) {
2570                 /*
2571                  * Find the base_fsp first without the stream.
2572                  */
2573                 saved_streamname = smb_fname_rel->stream_name;
2574                 smb_fname_rel->stream_name = NULL;
2575         }
2576
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,
2582                         nt_errstr(status));
2583                 goto fail;
2584         }
2585
2586         status = openat_pathref_fsp_case_insensitive(
2587                 smb_dirname->fsp, smb_fname_rel, ucf_flags);
2588
2589         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2590
2591                 char *normalized = NULL;
2592
2593                 if (VALID_STAT(smb_fname_rel->st)) {
2594                         /*
2595                          * If we're on an MSDFS share, see if this is
2596                          * an MSDFS link.
2597                          */
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))
2602                         {
2603                                 status = NT_STATUS_PATH_NOT_COVERED;
2604                                 goto fail;
2605                         }
2606
2607 #if defined(WITH_SMB1SERVER)
2608                         /*
2609                          * In SMB1 posix mode, if this is a symlink,
2610                          * allow access to the name with a NULL smb_fname->fsp.
2611                          */
2612                         if (!conn->sconn->using_smb2 &&
2613                                         posix &&
2614                                         S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
2615                                 SMB_ASSERT(smb_fname_rel->fsp == NULL);
2616                                 SMB_ASSERT(streamname == NULL);
2617
2618                                 smb_fname = full_path_from_dirfsp_atname(
2619                                                 mem_ctx,
2620                                                 smb_dirname->fsp,
2621                                                 smb_fname_rel);
2622                                 if (smb_fname == NULL) {
2623                                         status = NT_STATUS_NO_MEMORY;
2624                                         goto fail;
2625                                 }
2626                                 goto done;
2627                         }
2628 #endif
2629                         /*
2630                          * NT_STATUS_OBJECT_NAME_NOT_FOUND is
2631                          * misleading: The object exists but might be
2632                          * a symlink pointing outside the share.
2633                          */
2634                         goto fail;
2635                 }
2636
2637                 /*
2638                  * Creating a new file
2639                  */
2640
2641                 status = filename_convert_normalize_new(
2642                         smb_fname_rel,
2643                         conn,
2644                         smb_fname_rel->base_name,
2645                         &normalized);
2646                 if (!NT_STATUS_IS_OK(status)) {
2647                         DBG_DEBUG("filename_convert_normalize_new failed: "
2648                                   "%s\n",
2649                                   nt_errstr(status));
2650                         goto fail;
2651                 }
2652                 if (normalized != NULL) {
2653                         smb_fname_rel->base_name = normalized;
2654                 }
2655
2656                 smb_fname_rel->stream_name = saved_streamname;
2657
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;
2662                         goto fail;
2663                 }
2664                 goto done;
2665         }
2666
2667         if (!NT_STATUS_IS_OK(status)) {
2668                 goto fail;
2669         }
2670
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) {
2676                         goto fail;
2677                 }
2678                 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
2679                 if (!NT_STATUS_IS_OK(status)) {
2680                         goto fail;
2681                 }
2682                 goto done;
2683         }
2684
2685         base_fsp = smb_fname_rel->fsp;
2686         smb_fname_fsp_unlink(smb_fname_rel);
2687         SET_STAT_INVALID(smb_fname_rel->st);
2688
2689         smb_fname_rel->stream_name = saved_streamname;
2690
2691         status = open_stream_pathref_fsp(&base_fsp, smb_fname_rel);
2692
2693         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
2694             !conn->case_sensitive) {
2695                 char *found = NULL;
2696
2697                 status = get_real_stream_name(
2698                         smb_fname_rel,
2699                         base_fsp,
2700                         smb_fname_rel->stream_name,
2701                         &found);
2702
2703                 if (NT_STATUS_IS_OK(status)) {
2704                         smb_fname_rel->stream_name = found;
2705                         found = NULL;
2706                         status = open_stream_pathref_fsp(
2707                                 &base_fsp, smb_fname_rel);
2708                 }
2709         }
2710
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) {
2716                         goto fail;
2717                 }
2718                 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
2719                 if (!NT_STATUS_IS_OK(status)) {
2720                         goto fail;
2721                 }
2722                 goto done;
2723         }
2724
2725         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2726                 /*
2727                  * Creating a new stream
2728                  *
2729                  * We should save the already-open base fsp for
2730                  * create_file_unixpath() somehow.
2731                  */
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;
2736                         goto fail;
2737                 }
2738                 goto done;
2739         }
2740
2741         if (!NT_STATUS_IS_OK(status)) {
2742                 goto fail;
2743         }
2744
2745 done:
2746         *_dirfsp = smb_dirname->fsp;
2747         *_smb_fname = smb_fname;
2748
2749         smb_fname_fsp_unlink(smb_fname_rel);
2750         TALLOC_FREE(smb_fname_rel);
2751         return NT_STATUS_OK;
2752
2753 fail:
2754         TALLOC_FREE(dirname);
2755         TALLOC_FREE(smb_dirname);
2756         TALLOC_FREE(smb_fname_rel);
2757         return status;
2758 }
2759
2760 NTSTATUS filename_convert_dirfsp(
2761         TALLOC_CTX *mem_ctx,
2762         connection_struct *conn,
2763         const char *name_in,
2764         uint32_t ucf_flags,
2765         NTTIME twrp,
2766         struct files_struct **_dirfsp,
2767         struct smb_filename **_smb_fname)
2768 {
2769         char *substitute = NULL;
2770         size_t unparsed = 0;
2771         NTSTATUS status;
2772         char *target = NULL;
2773         char *abs_target = NULL;
2774         char *abs_target_canon = NULL;
2775         size_t symlink_redirects = 0;
2776         bool in_share;
2777
2778 next:
2779         if (symlink_redirects > 40) {
2780                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2781         }
2782
2783         status = filename_convert_dirfsp_nosymlink(
2784                 mem_ctx,
2785                 conn,
2786                 name_in,
2787                 ucf_flags,
2788                 twrp,
2789                 _dirfsp,
2790                 _smb_fname,
2791                 &substitute,
2792                 &unparsed);
2793
2794         if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
2795                 return status;
2796         }
2797
2798         if (!lp_follow_symlinks(SNUM(conn))) {
2799                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2800         }
2801
2802         /*
2803          * Right now, SMB2 and SMB1 always traverse symlinks
2804          * within the share. SMB1+POSIX traverses non-terminal
2805          * symlinks within the share.
2806          *
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.
2812          */
2813
2814         target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
2815         if (target == NULL) {
2816                 return NT_STATUS_NO_MEMORY;
2817         }
2818
2819         DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
2820                   name_in,
2821                   substitute,
2822                   unparsed,
2823                   target);
2824
2825         if (target[0] == '/') {
2826                 abs_target = target;
2827         } else {
2828                 abs_target = talloc_asprintf(
2829                         mem_ctx, "%s/%s", conn->connectpath, target);
2830                 if (abs_target == NULL) {
2831                         return NT_STATUS_NO_MEMORY;
2832                 }
2833         }
2834
2835         abs_target_canon = canonicalize_absolute_path(mem_ctx, abs_target);
2836         if (abs_target_canon == NULL) {
2837                 return NT_STATUS_NO_MEMORY;
2838         }
2839
2840         DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
2841
2842         in_share = strncmp(
2843                 abs_target_canon,
2844                 conn->connectpath,
2845                 strlen(conn->connectpath)) == 0;
2846         if (!in_share) {
2847                 DBG_DEBUG("wide link to %s\n", abs_target_canon);
2848                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2849         }
2850
2851         name_in = talloc_strdup(
2852                 mem_ctx, abs_target_canon + strlen(conn->connectpath) + 1);
2853
2854         symlink_redirects += 1;
2855
2856         goto next;
2857 }
2858
2859 /*
2860  * Build the full path from a dirfsp and dirfsp relative name
2861  */
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)
2866 {
2867         struct smb_filename *fname = NULL;
2868         char *path = NULL;
2869
2870         if (dirfsp == dirfsp->conn->cwd_fsp ||
2871             ISDOT(dirfsp->fsp_name->base_name) ||
2872             atname->base_name[0] == '/')
2873         {
2874                 path = talloc_strdup(mem_ctx, atname->base_name);
2875         } else {
2876                 path = talloc_asprintf(mem_ctx, "%s/%s",
2877                                        dirfsp->fsp_name->base_name,
2878                                        atname->base_name);
2879         }
2880         if (path == NULL) {
2881                 return NULL;
2882         }
2883
2884         fname = synthetic_smb_fname(mem_ctx,
2885                                     path,
2886                                     atname->stream_name,
2887                                     &atname->st,
2888                                     atname->twrp,
2889                                     atname->flags);
2890         TALLOC_FREE(path);
2891         if (fname == NULL) {
2892                 return NULL;
2893         }
2894
2895         return fname;
2896 }