s3: smbd: Inside filename_convert_dirfsp_nosymlink(), don't require UCF_PREP_CREATEFI...
[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         struct smb_filename *smb_fname = NULL;
1883         char *last_slash = NULL;
1884         char *orig_lcomp;
1885         char *fname = NULL;
1886         NTTIME twrp = 0;
1887         NTSTATUS status;
1888
1889         if (ucf_flags & UCF_DFS_PATHNAME) {
1890                 status = dfs_redirect(ctx,
1891                                 conn,
1892                                 filename_in,
1893                                 ucf_flags,
1894                                 !conn->sconn->using_smb2,
1895                                 &twrp,
1896                                 &fname);
1897                 if (!NT_STATUS_IS_OK(status)) {
1898                         DBG_DEBUG("dfs_redirect "
1899                                 "failed for name %s with %s\n",
1900                                 filename_in,
1901                                 nt_errstr(status));
1902                         return NULL;
1903                 }
1904                 filename_in = fname;
1905                 ucf_flags &= ~UCF_DFS_PATHNAME;
1906         }
1907
1908         /*
1909          * NB. We don't need to care about
1910          * is_fake_file_path(filename_in) here as these
1911          * code paths don't ever return original_lcomp
1912          * or use it anyway.
1913          */
1914
1915         if (ucf_flags & UCF_GMT_PATHNAME) {
1916                 /*
1917                  * Ensure we don't return a @GMT
1918                  * value as the last component.
1919                  */
1920                 smb_fname = synthetic_smb_fname(ctx,
1921                                         filename_in,
1922                                         NULL,
1923                                         NULL,
1924                                         twrp,
1925                                         0);
1926                 if (smb_fname == NULL) {
1927                         TALLOC_FREE(fname);
1928                         return NULL;
1929                 }
1930                 status = canonicalize_snapshot_path(smb_fname,
1931                                                     ucf_flags,
1932                                                     twrp);
1933                 if (!NT_STATUS_IS_OK(status)) {
1934                         TALLOC_FREE(fname);
1935                         TALLOC_FREE(smb_fname);
1936                         return NULL;
1937                 }
1938                 filename_in = smb_fname->base_name;
1939         }
1940         last_slash = strrchr(filename_in, '/');
1941         if (last_slash != NULL) {
1942                 orig_lcomp = talloc_strdup(ctx, last_slash+1);
1943         } else {
1944                 orig_lcomp = talloc_strdup(ctx, filename_in);
1945         }
1946         /* We're done with any temp names here. */
1947         TALLOC_FREE(smb_fname);
1948         TALLOC_FREE(fname);
1949         if (orig_lcomp == NULL) {
1950                 return NULL;
1951         }
1952         status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
1953         if (!NT_STATUS_IS_OK(status)) {
1954                 TALLOC_FREE(orig_lcomp);
1955                 return NULL;
1956         }
1957         return orig_lcomp;
1958 }
1959
1960 /**
1961  * Go through all the steps to validate a filename.
1962  *
1963  * @param ctx           talloc_ctx to allocate memory with.
1964  * @param conn          connection struct for vfs calls.
1965  * @param smbreq        SMB request if we're using privileges.
1966  * @param name_in       The unconverted name.
1967  * @param ucf_flags     flags to pass through to unix_convert().
1968  * @param twrp          Optional VSS time
1969  * @param p_cont_wcard  If not NULL, will be set to true if the dfs path
1970  *                      resolution detects a wildcard.
1971  * @param _smb_fname    The final converted name will be allocated if the
1972  *                      return is NT_STATUS_OK.
1973  *
1974  * @return NT_STATUS_OK if all operations completed successfully, appropriate
1975  *         error otherwise.
1976  */
1977 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1978                           connection_struct *conn,
1979                           const char *name_in,
1980                           uint32_t ucf_flags,
1981                           NTTIME twrp,
1982                           struct smb_filename **_smb_fname)
1983 {
1984         struct smb_filename *smb_fname = NULL;
1985         NTSTATUS status;
1986
1987         *_smb_fname = NULL;
1988
1989         if (ucf_flags & UCF_DFS_PATHNAME) {
1990                 char *fname = NULL;
1991                 NTTIME dfs_twrp = 0;
1992                 status = dfs_redirect(ctx, conn,
1993                                 name_in,
1994                                 ucf_flags,
1995                                 !conn->sconn->using_smb2,
1996                                 &dfs_twrp,
1997                                 &fname);
1998                 if (!NT_STATUS_IS_OK(status)) {
1999                         DBG_DEBUG("dfs_redirect "
2000                                 "failed for name %s with %s\n",
2001                                 name_in,
2002                                 nt_errstr(status));
2003                         return status;
2004                 }
2005                 name_in = fname;
2006                 ucf_flags &= ~UCF_DFS_PATHNAME;
2007                 if (twrp == 0 && dfs_twrp != 0) {
2008                         twrp = dfs_twrp;
2009                 }
2010         }
2011
2012         if (is_fake_file_path(name_in)) {
2013                 smb_fname = synthetic_smb_fname_split(ctx,
2014                                         name_in,
2015                                         (ucf_flags & UCF_POSIX_PATHNAMES));
2016                 if (smb_fname == NULL) {
2017                         return NT_STATUS_NO_MEMORY;
2018                 }
2019                 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2020                 smb_fname->st.st_ex_btime = (struct timespec){0, SAMBA_UTIME_OMIT};
2021                 smb_fname->st.st_ex_atime = (struct timespec){0, SAMBA_UTIME_OMIT};
2022                 smb_fname->st.st_ex_mtime = (struct timespec){0, SAMBA_UTIME_OMIT};
2023                 smb_fname->st.st_ex_ctime = (struct timespec){0, SAMBA_UTIME_OMIT};
2024
2025                 *_smb_fname = smb_fname;
2026                 return NT_STATUS_OK;
2027         }
2028
2029         status = unix_convert(ctx, conn, name_in, twrp, &smb_fname, ucf_flags);
2030         if (!NT_STATUS_IS_OK(status)) {
2031                 DBG_DEBUG("unix_convert failed "
2032                         "for name %s with %s\n",
2033                         name_in,
2034                         nt_errstr(status));
2035                 return status;
2036         }
2037
2038         if ((ucf_flags & UCF_POSIX_PATHNAMES) &&
2039             VALID_STAT(smb_fname->st) &&
2040             S_ISLNK(smb_fname->st.st_ex_mode))
2041         {
2042                 status = check_veto_path(conn, smb_fname);
2043                 if (!NT_STATUS_IS_OK(status)) {
2044                         TALLOC_FREE(smb_fname);
2045                         return status;
2046                 }
2047         } else {
2048                 status = check_name(conn, smb_fname);
2049         }
2050         if (!NT_STATUS_IS_OK(status)) {
2051                 DBG_NOTICE("check_name failed "
2052                         "for name %s with %s\n",
2053                         smb_fname_str_dbg(smb_fname),
2054                         nt_errstr(status));
2055                 TALLOC_FREE(smb_fname);
2056                 return status;
2057         }
2058
2059         if (!VALID_STAT(smb_fname->st)) {
2060                 DBG_DEBUG("[%s] does not exist, skipping pathref fsp\n",
2061                           smb_fname_str_dbg(smb_fname));
2062                 *_smb_fname = smb_fname;
2063                 return NT_STATUS_OK;
2064         }
2065
2066         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
2067         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2068                 /*
2069                  * We deal with symlinks here as we do in
2070                  * SMB_VFS_CREATE_FILE(): return success for POSIX clients with
2071                  * the notable difference that there will be no fsp in
2072                  * smb_fname->fsp.
2073                  *
2074                  * For Windows (non POSIX) clients fail with
2075                  * NT_STATUS_OBJECT_NAME_NOT_FOUND.
2076                  */
2077                 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH &&
2078                     S_ISLNK(smb_fname->st.st_ex_mode))
2079                 {
2080                         status = NT_STATUS_OK;
2081                 }
2082         }
2083         if (!NT_STATUS_IS_OK(status)) {
2084                 DBG_DEBUG("openat_pathref_fsp [%s] failed: %s\n",
2085                           smb_fname_str_dbg(smb_fname),
2086                           nt_errstr(status));
2087                 return status;
2088         }
2089
2090         *_smb_fname = smb_fname;
2091         return status;
2092 }
2093
2094 /*
2095  * Strip a @GMT component from an SMB1-DFS path. Could be anywhere
2096  * in the path.
2097  */
2098
2099 static char *strip_gmt_from_raw_dfs(TALLOC_CTX *ctx,
2100                                     const char *name_in,
2101                                     bool posix_pathnames,
2102                                     NTTIME *_twrp)
2103 {
2104         NTSTATUS status;
2105         struct smb_filename *smb_fname = NULL;
2106         char *name_out = NULL;
2107
2108         smb_fname = synthetic_smb_fname(ctx,
2109                                         name_in,
2110                                         NULL,
2111                                         NULL,
2112                                         0,
2113                                         0);
2114         if (smb_fname == NULL) {
2115                 return NULL;
2116         }
2117         if (!posix_pathnames) {
2118                 /*
2119                  * Raw DFS names are still '\\' separated.
2120                  * canonicalize_snapshot_path() only works
2121                  * on '/' separated paths. Convert.
2122                  */
2123                 string_replace(smb_fname->base_name, '\\', '/');
2124         }
2125         status = canonicalize_snapshot_path(smb_fname,
2126                                             UCF_GMT_PATHNAME,
2127                                             0);
2128         if (!NT_STATUS_IS_OK(status)) {
2129                 TALLOC_FREE(smb_fname);
2130                 return NULL;
2131         }
2132         if (!posix_pathnames) {
2133                 /* Replace as raw DFS names. */
2134                 string_replace(smb_fname->base_name, '/', '\\');
2135         }
2136         name_out = talloc_strdup(ctx, smb_fname->base_name);
2137         *_twrp = smb_fname->twrp;
2138         TALLOC_FREE(smb_fname);
2139         return name_out;
2140 }
2141
2142 /*
2143  * Deal with the SMB1 semantics of sending a pathname with a
2144  * wildcard as the terminal component for a SMB1search or
2145  * trans2 findfirst.
2146  */
2147
2148 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
2149                                            connection_struct *conn,
2150                                            const char *name_in,
2151                                            uint32_t ucf_flags,
2152                                            struct smb_filename **_smb_fname_out,
2153                                            char **_mask_out)
2154 {
2155         NTSTATUS status;
2156         char *p = NULL;
2157         char *mask = NULL;
2158         struct smb_filename *smb_fname = NULL;
2159         bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
2160         NTTIME twrp = 0;
2161         TALLOC_CTX *frame = talloc_stackframe();
2162
2163         *_smb_fname_out = NULL;
2164         *_mask_out = NULL;
2165
2166         DBG_DEBUG("name_in: %s\n", name_in);
2167
2168         if (ucf_flags & UCF_DFS_PATHNAME) {
2169                 /*
2170                  * We've been given a raw DFS pathname.
2171                  * In Windows mode this is separated by '\\'
2172                  * characters.
2173                  *
2174                  * We need to remove the last component
2175                  * which must be a wildcard before passing
2176                  * to dfs_redirect(). But the last component
2177                  * may also be a @GMT- token so we have to
2178                  * remove that first.
2179                  */
2180                 char path_sep = posix_pathnames ? '/' : '\\';
2181                 char *fname = NULL;
2182                 char *name_in_copy = NULL;
2183                 char *last_component = NULL;
2184
2185                 /* Work on a copy of name_in. */
2186                 if (ucf_flags & UCF_GMT_PATHNAME) {
2187                         name_in_copy = strip_gmt_from_raw_dfs(frame,
2188                                                               name_in,
2189                                                               posix_pathnames,
2190                                                               &twrp);
2191                         ucf_flags &= ~UCF_GMT_PATHNAME;
2192                 } else {
2193                         name_in_copy = talloc_strdup(frame, name_in);
2194                 }
2195                 if (name_in_copy == NULL) {
2196                         TALLOC_FREE(frame);
2197                         return NT_STATUS_NO_MEMORY;
2198                 }
2199
2200                 /*
2201                  * Now we know that the last component is the
2202                  * wildcard. Copy it and truncate to remove it.
2203                  */
2204                 p = strrchr_m(name_in_copy, path_sep);
2205                 if (p == NULL) {
2206                         last_component = talloc_strdup(frame, name_in_copy);
2207                         name_in_copy[0] = '\0';
2208                 } else {
2209                         last_component = talloc_strdup(frame, p+1);
2210                         *p = '\0';
2211                 }
2212                 if (last_component == NULL) {
2213                         TALLOC_FREE(frame);
2214                         return NT_STATUS_NO_MEMORY;
2215                 }
2216
2217                 DBG_DEBUG("name_in_copy: %s\n", name_in);
2218
2219                 /*
2220                  * Now we can call dfs_redirect()
2221                  * on the name without wildcard.
2222                  */
2223                 status = dfs_redirect(frame,
2224                                       conn,
2225                                       name_in_copy,
2226                                       ucf_flags,
2227                                       !conn->sconn->using_smb2,
2228                                       NULL,
2229                                       &fname);
2230                 if (!NT_STATUS_IS_OK(status)) {
2231                         DBG_DEBUG("dfs_redirect "
2232                                 "failed for name %s with %s\n",
2233                                 name_in_copy,
2234                                 nt_errstr(status));
2235                         TALLOC_FREE(frame);
2236                         return status;
2237                 }
2238                 /* Add the last component back. */
2239                 if (fname[0] == '\0') {
2240                         name_in = talloc_strdup(frame, last_component);
2241                 } else {
2242                         name_in = talloc_asprintf(frame,
2243                                                   "%s%c%s",
2244                                                   fname,
2245                                                   path_sep,
2246                                                   last_component);
2247                 }
2248                 if (name_in == NULL) {
2249                         TALLOC_FREE(frame);
2250                         return NT_STATUS_NO_MEMORY;
2251                 }
2252                 ucf_flags &= ~UCF_DFS_PATHNAME;
2253
2254                 DBG_DEBUG("After DFS redirect name_in: %s\n", name_in);
2255         }
2256
2257         smb_fname = synthetic_smb_fname(frame,
2258                                         name_in,
2259                                         NULL,
2260                                         NULL,
2261                                         twrp,
2262                                         posix_pathnames ?
2263                                                 SMB_FILENAME_POSIX_PATH : 0);
2264         if (smb_fname == NULL) {
2265                 TALLOC_FREE(frame);
2266                 return NT_STATUS_NO_MEMORY;
2267         }
2268
2269         /* Canonicalize any @GMT- paths. */
2270         status = canonicalize_snapshot_path(smb_fname, ucf_flags, twrp);
2271         if (!NT_STATUS_IS_OK(status)) {
2272                 TALLOC_FREE(frame);
2273                 return status;
2274         }
2275
2276         /* Get the original lcomp. */
2277         mask = get_original_lcomp(frame,
2278                                   conn,
2279                                   name_in,
2280                                   ucf_flags);
2281         if (mask == NULL) {
2282                 TALLOC_FREE(frame);
2283                 return NT_STATUS_NO_MEMORY;
2284         }
2285
2286         if (mask[0] == '\0') {
2287                 /* Windows and OS/2 systems treat search on the root as * */
2288                 TALLOC_FREE(mask);
2289                 mask = talloc_strdup(frame, "*");
2290                 if (mask == NULL) {
2291                         TALLOC_FREE(frame);
2292                         return NT_STATUS_NO_MEMORY;
2293                 }
2294         }
2295
2296         DBG_DEBUG("mask = %s\n", mask);
2297
2298         /*
2299          * Remove the terminal component so
2300          * filename_convert never sees the mask.
2301          */
2302         p = strrchr_m(smb_fname->base_name,'/');
2303         if (p == NULL) {
2304                 /* filename_convert handles a '\0' base_name. */
2305                 smb_fname->base_name[0] = '\0';
2306         } else {
2307                 *p = '\0';
2308         }
2309
2310         DBG_DEBUG("For filename_convert: smb_fname = %s\n",
2311                 smb_fname_str_dbg(smb_fname));
2312
2313         /* Convert the parent directory path. */
2314         status = filename_convert(frame,
2315                                   conn,
2316                                   smb_fname->base_name,
2317                                   ucf_flags,
2318                                   smb_fname->twrp,
2319                                   &smb_fname);
2320
2321         if (NT_STATUS_IS_OK(status)) {
2322                 *_smb_fname_out = talloc_move(ctx, &smb_fname);
2323                 *_mask_out = talloc_move(ctx, &mask);
2324         } else {
2325                 DBG_DEBUG("filename_convert error for %s: %s\n",
2326                         smb_fname_str_dbg(smb_fname),
2327                         nt_errstr(status));
2328         }
2329
2330         TALLOC_FREE(frame);
2331         return status;
2332 }
2333
2334 /*
2335  * Get the correct capitalized stream name hanging off
2336  * base_fsp. Equivalent of get_real_filename(), but for streams.
2337  */
2338 static NTSTATUS get_real_stream_name(
2339         TALLOC_CTX *mem_ctx,
2340         struct files_struct *base_fsp,
2341         const char *stream_name,
2342         char **_found)
2343 {
2344         unsigned int i, num_streams = 0;
2345         struct stream_struct *streams = NULL;
2346         NTSTATUS status;
2347
2348         status = vfs_fstreaminfo(
2349                 base_fsp, talloc_tos(), &num_streams, &streams);
2350         if (!NT_STATUS_IS_OK(status)) {
2351                 return status;
2352         }
2353
2354         for (i=0; i<num_streams; i++) {
2355                 bool equal = sname_equal(stream_name, streams[i].name, false);
2356
2357                 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
2358                           stream_name,
2359                           streams[i].name,
2360                           equal ? "" : "not ");
2361
2362                 if (equal) {
2363                         *_found = talloc_move(mem_ctx, &streams[i].name);
2364                         TALLOC_FREE(streams);
2365                         return NT_STATUS_OK;
2366                 }
2367         }
2368
2369         TALLOC_FREE(streams);
2370         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2371 }
2372
2373 static bool filename_split_lcomp(
2374         TALLOC_CTX *mem_ctx,
2375         const char *name_in,
2376         bool posix,
2377         char **_dirname,
2378         const char **_fname_rel,
2379         const char **_streamname)
2380 {
2381         const char *lcomp = NULL;
2382         const char *fname_rel = NULL;
2383         const char *streamname = NULL;
2384         char *dirname = NULL;
2385
2386         if (name_in[0] == '\0') {
2387                 fname_rel = ".";
2388                 dirname = talloc_strdup(mem_ctx, "");
2389                 if (dirname == NULL) {
2390                         return false;
2391                 }
2392                 goto done;
2393         }
2394
2395         lcomp = strrchr_m(name_in, '/');
2396         if (lcomp != NULL) {
2397                 fname_rel = lcomp+1;
2398                 dirname = talloc_strndup(mem_ctx, name_in, lcomp - name_in);
2399                 if (dirname == NULL) {
2400                         return false;
2401                 }
2402                 goto find_stream;
2403         }
2404
2405         /*
2406          * No slash, dir is emtpy
2407          */
2408         dirname = talloc_strdup(mem_ctx, "");
2409         if (dirname == NULL) {
2410                 return false;
2411         }
2412
2413         if (!posix && (name_in[0] == ':')) {
2414                 /*
2415                  * Special case for stream on root directory
2416                  */
2417                 fname_rel = ".";
2418                 streamname = name_in;
2419                 goto done;
2420         }
2421
2422         fname_rel = name_in;
2423
2424 find_stream:
2425         if (!posix) {
2426                 streamname = strchr_m(fname_rel, ':');
2427
2428                 if (streamname != NULL) {
2429                         fname_rel = talloc_strndup(
2430                                 mem_ctx,
2431                                 fname_rel,
2432                                 streamname - fname_rel);
2433                         if (fname_rel == NULL) {
2434                                 TALLOC_FREE(dirname);
2435                                 return false;
2436                         }
2437                 }
2438         }
2439
2440 done:
2441         *_dirname = dirname;
2442         *_fname_rel = fname_rel;
2443         *_streamname = streamname;
2444         return true;
2445 }
2446
2447 /*
2448  * Create the correct capitalization of a file name to be created.
2449  */
2450 static NTSTATUS filename_convert_normalize_new(
2451         TALLOC_CTX *mem_ctx,
2452         struct connection_struct *conn,
2453         char *name_in,
2454         char **_normalized)
2455 {
2456         char *name = name_in;
2457
2458         *_normalized = NULL;
2459
2460         if (!conn->case_preserve ||
2461             (mangle_is_8_3(name, false,
2462                            conn->params) &&
2463              !conn->short_case_preserve)) {
2464
2465                 char *normalized = talloc_strdup(mem_ctx, name);
2466                 if (normalized == NULL) {
2467                         return NT_STATUS_NO_MEMORY;
2468                 }
2469
2470                 strnorm(normalized, lp_default_case(SNUM(conn)));
2471                 name = normalized;
2472         }
2473
2474         if (mangle_is_mangled(name, conn->params)) {
2475                 bool found;
2476                 char *unmangled = NULL;
2477
2478                 found = mangle_lookup_name_from_8_3(
2479                         mem_ctx, name, &unmangled, conn->params);
2480                 if (found) {
2481                         name = unmangled;
2482                 }
2483         }
2484
2485         if (name != name_in) {
2486                 *_normalized = name;
2487         }
2488
2489         return NT_STATUS_OK;
2490 }
2491
2492 /*
2493  * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
2494  * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
2495  * the first attempt based on the filename sent by the client gives
2496  * ENOENT.
2497  */
2498 static NTSTATUS openat_pathref_fsp_case_insensitive(
2499         struct files_struct *dirfsp,
2500         struct smb_filename *smb_fname_rel,
2501         uint32_t ucf_flags)
2502 {
2503         const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2504         DATA_BLOB cache_key = { .data = NULL, };
2505         char *found_name = NULL;
2506         NTSTATUS status;
2507         bool ok;
2508
2509         SET_STAT_INVALID(smb_fname_rel->st);
2510
2511         status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2512
2513         if (NT_STATUS_IS_OK(status)) {
2514                 return NT_STATUS_OK;
2515         }
2516
2517         if (VALID_STAT(smb_fname_rel->st)) {
2518                 /*
2519                  * We got an error although the object existed. Might
2520                  * be a symlink we don't want.
2521                  */
2522                 return status;
2523         }
2524
2525         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2526                 /*
2527                  * Only retry on ENOENT
2528                  */
2529                 return status;
2530         }
2531
2532         if (posix || dirfsp->conn->case_sensitive) {
2533                 /*
2534                  * Only return case insensitive if required
2535                  */
2536                 return status;
2537         }
2538
2539         if (lp_stat_cache()) {
2540                 char *base_name = smb_fname_rel->base_name;
2541                 DATA_BLOB value = { .data = NULL };
2542
2543                 ok = get_real_filename_cache_key(
2544                         talloc_tos(), dirfsp, base_name, &cache_key);
2545                 if (!ok) {
2546                         /*
2547                          * probably ENOMEM, just bail
2548                          */
2549                         return status;
2550                 }
2551
2552                 DO_PROFILE_INC(statcache_lookups);
2553
2554                 ok = memcache_lookup(
2555                         NULL, GETREALFILENAME_CACHE, cache_key, &value);
2556                 if (!ok) {
2557                         DO_PROFILE_INC(statcache_misses);
2558                         goto lookup;
2559                 }
2560                 DO_PROFILE_INC(statcache_hits);
2561
2562                 TALLOC_FREE(smb_fname_rel->base_name);
2563                 smb_fname_rel->base_name = talloc_memdup(
2564                         smb_fname_rel, value.data, value.length);
2565                 if (smb_fname_rel->base_name == NULL) {
2566                         TALLOC_FREE(cache_key.data);
2567                         return NT_STATUS_NO_MEMORY;
2568                 }
2569
2570                 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2571                 if (NT_STATUS_IS_OK(status)) {
2572                         TALLOC_FREE(cache_key.data);
2573                         return NT_STATUS_OK;
2574                 }
2575
2576                 memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
2577         }
2578
2579 lookup:
2580         status = get_real_filename_at(
2581                 dirfsp, smb_fname_rel->base_name, smb_fname_rel, &found_name);
2582         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
2583             (ucf_flags & UCF_PREP_CREATEFILE)) {
2584                 /*
2585                  * dropbox
2586                  */
2587                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2588         }
2589
2590         if (NT_STATUS_IS_OK(status)) {
2591                 TALLOC_FREE(smb_fname_rel->base_name);
2592                 smb_fname_rel->base_name = found_name;
2593
2594                 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
2595         }
2596
2597         if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
2598                 DATA_BLOB value = {
2599                         .data = (uint8_t *)smb_fname_rel->base_name,
2600                         .length = strlen(smb_fname_rel->base_name) + 1,
2601                 };
2602
2603                 memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
2604         }
2605
2606         TALLOC_FREE(cache_key.data);
2607
2608         return status;
2609 }
2610
2611 /*
2612  * Split up name_in as sent by the client into a directory pathref fsp
2613  * and a relative smb_filename.
2614  */
2615 static const char *previous_slash(const char *name_in, const char *slash)
2616 {
2617         const char *prev = name_in;
2618
2619         while (true) {
2620                 const char *next = strchr_m(prev, '/');
2621
2622                 SMB_ASSERT(next != NULL); /* we have at least one slash */
2623
2624                 if (next == slash) {
2625                         break;
2626                 }
2627
2628                 prev = next+1;
2629         };
2630
2631         if (prev == name_in) {
2632                 /* no previous slash */
2633                 return NULL;
2634         }
2635
2636         return prev;
2637 }
2638
2639 static char *symlink_target_path(
2640         TALLOC_CTX *mem_ctx,
2641         const char *name_in,
2642         const char *substitute,
2643         size_t unparsed)
2644 {
2645         size_t name_in_len = strlen(name_in);
2646         const char *p_unparsed = NULL;
2647         const char *parent = NULL;
2648         char *ret;
2649
2650         SMB_ASSERT(unparsed <= name_in_len);
2651
2652         p_unparsed = name_in + (name_in_len - unparsed);
2653
2654         if (substitute[0] == '/') {
2655                 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
2656                 return ret;
2657         }
2658
2659         if (unparsed == 0) {
2660                 parent = strrchr_m(name_in, '/');
2661         } else {
2662                 parent = previous_slash(name_in, p_unparsed);
2663         }
2664
2665         if (parent == NULL) {
2666                 /* no previous slash */
2667                 parent = name_in;
2668         }
2669
2670         ret = talloc_asprintf(
2671                 mem_ctx,
2672                 "%.*s%s%s",
2673                 (int)(parent - name_in),
2674                 name_in,
2675                 substitute,
2676                 p_unparsed);
2677         return ret;
2678 }
2679
2680 /*
2681  * Split up name_in as sent by the client into a directory pathref fsp
2682  * and a relative smb_filename.
2683  */
2684 static NTSTATUS filename_convert_dirfsp_nosymlink(
2685         TALLOC_CTX *mem_ctx,
2686         connection_struct *conn,
2687         const char *name_in,
2688         uint32_t ucf_flags,
2689         NTTIME twrp,
2690         struct files_struct **_dirfsp,
2691         struct smb_filename **_smb_fname,
2692         char **_substitute,
2693         size_t *_unparsed)
2694 {
2695         struct smb_filename *smb_dirname = NULL;
2696         struct smb_filename *smb_fname_rel = NULL;
2697         struct smb_filename *smb_fname = NULL;
2698         const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
2699         char *dirname = NULL;
2700         const char *fname_rel = NULL;
2701         const char *streamname = NULL;
2702         char *saved_streamname = NULL;
2703         struct files_struct *base_fsp = NULL;
2704         bool ok;
2705         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2706
2707         if (ucf_flags & UCF_DFS_PATHNAME) {
2708                 char *fname = NULL;
2709                 NTTIME dfs_twrp = 0;
2710                 status = dfs_redirect(
2711                         mem_ctx,
2712                         conn,
2713                         name_in,
2714                         ucf_flags,
2715                         !conn->sconn->using_smb2,
2716                         &dfs_twrp,
2717                         &fname);
2718                 if (!NT_STATUS_IS_OK(status)) {
2719                         DBG_DEBUG("dfs_redirect "
2720                                 "failed for name %s with %s\n",
2721                                 name_in,
2722                                 nt_errstr(status));
2723                         return status;
2724                 }
2725                 name_in = fname;
2726                 ucf_flags &= ~UCF_DFS_PATHNAME;
2727                 if (twrp == 0 && dfs_twrp != 0) {
2728                         twrp = dfs_twrp;
2729                 }
2730         }
2731
2732         if (is_fake_file_path(name_in) || conn->printer) {
2733                 smb_fname = synthetic_smb_fname_split(mem_ctx, name_in, posix);
2734                 if (smb_fname == NULL) {
2735                         return NT_STATUS_NO_MEMORY;
2736                 }
2737                 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2738                 smb_fname->st.st_ex_btime =
2739                         (struct timespec){0, SAMBA_UTIME_OMIT};
2740                 smb_fname->st.st_ex_atime =
2741                         (struct timespec){0, SAMBA_UTIME_OMIT};
2742                 smb_fname->st.st_ex_mtime =
2743                         (struct timespec){0, SAMBA_UTIME_OMIT};
2744                 smb_fname->st.st_ex_ctime =
2745                         (struct timespec){0, SAMBA_UTIME_OMIT};
2746
2747                 *_dirfsp = conn->cwd_fsp;
2748                 *_smb_fname = smb_fname;
2749                 return NT_STATUS_OK;
2750         }
2751
2752         /*
2753          * Catch an invalid path of "." before we
2754          * call filename_split_lcomp(). We need to
2755          * do this as filename_split_lcomp() will
2756          * use "." for the missing relative component
2757          * when an empty name_in path is sent by
2758          * the client.
2759          */
2760         if (ISDOT(name_in)) {
2761                 status = NT_STATUS_OBJECT_NAME_INVALID;
2762                 goto fail;
2763         }
2764
2765         ok = filename_split_lcomp(
2766                 talloc_tos(),
2767                 name_in,
2768                 posix,
2769                 &dirname,
2770                 &fname_rel,
2771                 &streamname);
2772         if (!ok) {
2773                 status = NT_STATUS_NO_MEMORY;
2774                 goto fail;
2775         }
2776
2777         if (!posix) {
2778                 bool name_has_wild = ms_has_wild(dirname);
2779                 name_has_wild |= ms_has_wild(fname_rel);
2780                 if (name_has_wild) {
2781                         status = NT_STATUS_OBJECT_NAME_INVALID;
2782                         goto fail;
2783                 }
2784         }
2785
2786         if (dirname[0] == '\0') {
2787                 status = synthetic_pathref(
2788                         mem_ctx,
2789                         conn->cwd_fsp,
2790                         ".",
2791                         NULL,
2792                         NULL,
2793                         0,
2794                         posix ? SMB_FILENAME_POSIX_PATH : 0,
2795                         &smb_dirname);
2796         } else {
2797                 char *substitute = NULL;
2798                 size_t unparsed = 0;
2799
2800                 status = openat_pathref_dirfsp_nosymlink(
2801                         mem_ctx,
2802                         conn,
2803                         dirname,
2804                         0,
2805                         &smb_dirname,
2806                         &unparsed,
2807                         &substitute);
2808
2809                 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
2810
2811                         size_t name_in_len = strlen(name_in);
2812                         size_t dirname_len = strlen(dirname);
2813
2814                         SMB_ASSERT(name_in_len >= dirname_len);
2815
2816                         *_substitute = substitute;
2817                         *_unparsed = unparsed + (name_in_len - dirname_len);
2818
2819                         goto fail;
2820                 }
2821         }
2822
2823         if (!NT_STATUS_IS_OK(status)) {
2824                 DBG_DEBUG("opening directory %s failed: %s\n",
2825                           dirname,
2826                           nt_errstr(status));
2827                 TALLOC_FREE(dirname);
2828
2829                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2830                         /*
2831                          * Except ACCESS_DENIED, everything else leads
2832                          * to PATH_NOT_FOUND.
2833                          */
2834                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2835                 }
2836
2837                 goto fail;
2838         }
2839
2840         if (!VALID_STAT_OF_DIR(smb_dirname->st)) {
2841                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2842                 goto fail;
2843         }
2844
2845         /*
2846          * Only look at bad last component values
2847          * once we know we have a valid directory. That
2848          * way we won't confuse error messages from
2849          * opening the directory path with error
2850          * messages from a bad last component.
2851          */
2852
2853         /* Relative filename can't be empty */
2854         if (fname_rel[0] == '\0') {
2855                 status = NT_STATUS_OBJECT_NAME_INVALID;
2856                 goto fail;
2857         }
2858
2859         /* Relative filename can't be ".." */
2860         if (ISDOTDOT(fname_rel)) {
2861                 status = NT_STATUS_OBJECT_NAME_INVALID;
2862                 goto fail;
2863         }
2864         /* Relative name can only be dot if directory is empty. */
2865         if (ISDOT(fname_rel) && dirname[0] != '\0') {
2866                 status = NT_STATUS_OBJECT_NAME_INVALID;
2867                 goto fail;
2868         }
2869
2870         TALLOC_FREE(dirname);
2871
2872         smb_fname_rel = synthetic_smb_fname(
2873                 mem_ctx,
2874                 fname_rel,
2875                 streamname,
2876                 NULL,
2877                 twrp,
2878                 posix ? SMB_FILENAME_POSIX_PATH : 0);
2879         if (smb_fname_rel == NULL) {
2880                 status = NT_STATUS_NO_MEMORY;
2881                 goto fail;
2882         }
2883
2884         if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
2885             is_named_stream(smb_fname_rel)) {
2886                 /*
2887                  * Find the base_fsp first without the stream.
2888                  */
2889                 saved_streamname = smb_fname_rel->stream_name;
2890                 smb_fname_rel->stream_name = NULL;
2891         }
2892
2893         status = normalize_filename_case(
2894                 conn, smb_fname_rel->base_name, ucf_flags);
2895         if (!NT_STATUS_IS_OK(status)) {
2896                 DBG_ERR("normalize_filename_case %s failed: %s\n",
2897                         smb_fname_rel->base_name,
2898                         nt_errstr(status));
2899                 goto fail;
2900         }
2901
2902         status = openat_pathref_fsp_case_insensitive(
2903                 smb_dirname->fsp, smb_fname_rel, ucf_flags);
2904
2905         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2906
2907                 char *normalized = NULL;
2908
2909                 if (VALID_STAT(smb_fname_rel->st)) {
2910 #if defined(WITH_SMB1SERVER)
2911                         /*
2912                          * In SMB1 posix mode, if this is a symlink,
2913                          * allow access to the name with a NULL smb_fname->fsp.
2914                          */
2915                         if (!conn->sconn->using_smb2 &&
2916                                         posix &&
2917                                         S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
2918                                 SMB_ASSERT(smb_fname_rel->fsp == NULL);
2919                                 SMB_ASSERT(streamname == NULL);
2920
2921                                 smb_fname = full_path_from_dirfsp_atname(
2922                                                 mem_ctx,
2923                                                 smb_dirname->fsp,
2924                                                 smb_fname_rel);
2925                                 if (smb_fname == NULL) {
2926                                         status = NT_STATUS_NO_MEMORY;
2927                                         goto fail;
2928                                 }
2929                                 goto done;
2930                         }
2931 #endif
2932                         /*
2933                          * NT_STATUS_OBJECT_NAME_NOT_FOUND is
2934                          * misleading: The object exists but might be
2935                          * a symlink pointing outside the share.
2936                          */
2937                         goto fail;
2938                 }
2939
2940                 /*
2941                  * Creating a new file
2942                  */
2943
2944                 status = filename_convert_normalize_new(
2945                         smb_fname_rel,
2946                         conn,
2947                         smb_fname_rel->base_name,
2948                         &normalized);
2949                 if (!NT_STATUS_IS_OK(status)) {
2950                         DBG_DEBUG("filename_convert_normalize_new failed: "
2951                                   "%s\n",
2952                                   nt_errstr(status));
2953                         goto fail;
2954                 }
2955                 if (normalized != NULL) {
2956                         smb_fname_rel->base_name = normalized;
2957                 }
2958
2959                 smb_fname_rel->stream_name = saved_streamname;
2960
2961                 smb_fname = full_path_from_dirfsp_atname(
2962                         mem_ctx, smb_dirname->fsp, smb_fname_rel);
2963                 if (smb_fname == NULL) {
2964                         status = NT_STATUS_NO_MEMORY;
2965                         goto fail;
2966                 }
2967                 goto done;
2968         }
2969
2970         if (!NT_STATUS_IS_OK(status)) {
2971                 goto fail;
2972         }
2973
2974         if (saved_streamname == NULL) {
2975                 /* smb_fname must be allocated off mem_ctx. */
2976                 smb_fname = cp_smb_filename(mem_ctx,
2977                                             smb_fname_rel->fsp->fsp_name);
2978                 if (smb_fname == NULL) {
2979                         goto fail;
2980                 }
2981                 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
2982                 if (!NT_STATUS_IS_OK(status)) {
2983                         goto fail;
2984                 }
2985                 goto done;
2986         }
2987
2988         base_fsp = smb_fname_rel->fsp;
2989         smb_fname_fsp_unlink(smb_fname_rel);
2990         SET_STAT_INVALID(smb_fname_rel->st);
2991
2992         smb_fname_rel->stream_name = saved_streamname;
2993
2994         status = open_stream_pathref_fsp(&base_fsp, smb_fname_rel);
2995
2996         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
2997             !conn->case_sensitive) {
2998                 char *found = NULL;
2999
3000                 status = get_real_stream_name(
3001                         smb_fname_rel,
3002                         base_fsp,
3003                         smb_fname_rel->stream_name,
3004                         &found);
3005
3006                 if (NT_STATUS_IS_OK(status)) {
3007                         smb_fname_rel->stream_name = found;
3008                         found = NULL;
3009                         status = open_stream_pathref_fsp(
3010                                 &base_fsp, smb_fname_rel);
3011                 }
3012         }
3013
3014         if (NT_STATUS_IS_OK(status)) {
3015                 /* smb_fname must be allocated off mem_ctx. */
3016                 smb_fname = cp_smb_filename(mem_ctx,
3017                                             smb_fname_rel->fsp->fsp_name);
3018                 if (smb_fname == NULL) {
3019                         goto fail;
3020                 }
3021                 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
3022                 if (!NT_STATUS_IS_OK(status)) {
3023                         goto fail;
3024                 }
3025                 goto done;
3026         }
3027
3028         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3029                 /*
3030                  * Creating a new stream
3031                  *
3032                  * We should save the already-open base fsp for
3033                  * create_file_unixpath() somehow.
3034                  */
3035                 smb_fname = full_path_from_dirfsp_atname(
3036                         mem_ctx, smb_dirname->fsp, smb_fname_rel);
3037                 if (smb_fname == NULL) {
3038                         status = NT_STATUS_NO_MEMORY;
3039                         goto fail;
3040                 }
3041                 goto done;
3042         }
3043
3044         if (!NT_STATUS_IS_OK(status)) {
3045                 goto fail;
3046         }
3047
3048 done:
3049         *_dirfsp = smb_dirname->fsp;
3050         *_smb_fname = smb_fname;
3051
3052         smb_fname_fsp_unlink(smb_fname_rel);
3053         TALLOC_FREE(smb_fname_rel);
3054         return NT_STATUS_OK;
3055
3056 fail:
3057         TALLOC_FREE(dirname);
3058         TALLOC_FREE(smb_dirname);
3059         TALLOC_FREE(smb_fname_rel);
3060         return status;
3061 }
3062
3063 NTSTATUS filename_convert_dirfsp(
3064         TALLOC_CTX *mem_ctx,
3065         connection_struct *conn,
3066         const char *name_in,
3067         uint32_t ucf_flags,
3068         NTTIME twrp,
3069         struct files_struct **_dirfsp,
3070         struct smb_filename **_smb_fname)
3071 {
3072         char *substitute = NULL;
3073         size_t unparsed = 0;
3074         NTSTATUS status;
3075         char *target = NULL;
3076         char *abs_target = NULL;
3077         char *abs_target_canon = NULL;
3078         size_t symlink_redirects = 0;
3079         bool in_share;
3080
3081 next:
3082         if (symlink_redirects > 40) {
3083                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3084         }
3085
3086         status = filename_convert_dirfsp_nosymlink(
3087                 mem_ctx,
3088                 conn,
3089                 name_in,
3090                 ucf_flags,
3091                 twrp,
3092                 _dirfsp,
3093                 _smb_fname,
3094                 &substitute,
3095                 &unparsed);
3096
3097 #if defined(WITH_SMB1SERVER)
3098         /*
3099          * This isn't 100% correct, but it gets us close enough
3100          * to the old behavior for SMB1+POSIX libsmbclient. If we went through a
3101          * symlink, and we got NT_STATUS_ACCESS_DENIED on the directory
3102          * containing the target, just don't allow the client to see the
3103          * intermediate path.
3104          */
3105         if (!conn->sconn->using_smb2 &&
3106                         (ucf_flags & UCF_POSIX_PATHNAMES) &&
3107                         symlink_redirects > 0 &&
3108                         NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3109                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3110         }
3111 #endif
3112
3113         if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
3114                 return status;
3115         }
3116
3117         if (!lp_follow_symlinks(SNUM(conn))) {
3118                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3119         }
3120
3121         /*
3122          * Right now, SMB2 and SMB1 always traverse symlinks
3123          * within the share. SMB1+POSIX traverses non-terminal
3124          * symlinks within the share.
3125          *
3126          * When we add SMB2+POSIX we need to return
3127          * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
3128          * symlink target data read below if SMB2+POSIX has
3129          * UCF_POSIX_PATHNAMES set to cause the client to
3130          * resolve all symlinks locally.
3131          */
3132
3133         target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
3134         if (target == NULL) {
3135                 return NT_STATUS_NO_MEMORY;
3136         }
3137
3138         DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
3139                   name_in,
3140                   substitute,
3141                   unparsed,
3142                   target);
3143
3144         if (target[0] == '/') {
3145                 abs_target = target;
3146         } else {
3147                 abs_target = talloc_asprintf(
3148                         mem_ctx, "%s/%s", conn->connectpath, target);
3149                 if (abs_target == NULL) {
3150                         return NT_STATUS_NO_MEMORY;
3151                 }
3152         }
3153
3154         abs_target_canon = canonicalize_absolute_path(mem_ctx, abs_target);
3155         if (abs_target_canon == NULL) {
3156                 return NT_STATUS_NO_MEMORY;
3157         }
3158
3159         DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
3160
3161         in_share = strncmp(
3162                 abs_target_canon,
3163                 conn->connectpath,
3164                 strlen(conn->connectpath)) == 0;
3165         if (!in_share) {
3166                 DBG_DEBUG("wide link to %s\n", abs_target_canon);
3167                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3168         }
3169
3170         name_in = talloc_strdup(
3171                 mem_ctx, abs_target_canon + strlen(conn->connectpath) + 1);
3172
3173         symlink_redirects += 1;
3174
3175         goto next;
3176 }
3177
3178 /*
3179  * Build the full path from a dirfsp and dirfsp relative name
3180  */
3181 struct smb_filename *full_path_from_dirfsp_atname(
3182         TALLOC_CTX *mem_ctx,
3183         const struct files_struct *dirfsp,
3184         const struct smb_filename *atname)
3185 {
3186         struct smb_filename *fname = NULL;
3187         char *path = NULL;
3188
3189         if (dirfsp == dirfsp->conn->cwd_fsp ||
3190             ISDOT(dirfsp->fsp_name->base_name) ||
3191             atname->base_name[0] == '/')
3192         {
3193                 path = talloc_strdup(mem_ctx, atname->base_name);
3194         } else {
3195                 path = talloc_asprintf(mem_ctx, "%s/%s",
3196                                        dirfsp->fsp_name->base_name,
3197                                        atname->base_name);
3198         }
3199         if (path == NULL) {
3200                 return NULL;
3201         }
3202
3203         fname = synthetic_smb_fname(mem_ctx,
3204                                     path,
3205                                     atname->stream_name,
3206                                     &atname->st,
3207                                     atname->twrp,
3208                                     atname->flags);
3209         TALLOC_FREE(path);
3210         if (fname == NULL) {
3211                 return NULL;
3212         }
3213
3214         return fname;
3215 }