5988396ee130e479f899f751ab0897b45a2ecdfa
[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
33 static int get_real_filename(connection_struct *conn,
34                              struct smb_filename *path,
35                              const char *name,
36                              TALLOC_CTX *mem_ctx,
37                              char **found_name);
38
39 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
40 {
41         uint32_t ucf_flags = 0;
42
43         if (req != NULL) {
44                 if (req->posix_pathnames) {
45                         ucf_flags |= UCF_POSIX_PATHNAMES;
46                 }
47                 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
48                         ucf_flags |= UCF_DFS_PATHNAME;
49                 }
50                 if (req->flags2 & FLAGS2_REPARSE_PATH) {
51                         ucf_flags |= UCF_GMT_PATHNAME;
52                 }
53         }
54
55         return ucf_flags;
56 }
57
58 uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
59 {
60         uint32_t ucf_flags = 0;
61
62         ucf_flags |= ucf_flags_from_smb_request(req);
63
64         switch (create_disposition) {
65         case FILE_OPEN:
66         case FILE_OVERWRITE:
67                 break;
68         case FILE_SUPERSEDE:
69         case FILE_CREATE:
70         case FILE_OPEN_IF:
71         case FILE_OVERWRITE_IF:
72                 ucf_flags |= UCF_PREP_CREATEFILE;
73                 break;
74         }
75
76         return ucf_flags;
77 }
78
79 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
80                                   connection_struct *conn,
81                                   struct smb_filename *smb_fname);
82
83 /****************************************************************************
84  Mangle the 2nd name and check if it is then equal to the first name.
85 ****************************************************************************/
86
87 static bool mangled_equal(const char *name1,
88                         const char *name2,
89                         const struct share_params *p)
90 {
91         char mname[13];
92
93         if (!name_to_8_3(name2, mname, False, p)) {
94                 return False;
95         }
96         return strequal(name1, mname);
97 }
98
99 /****************************************************************************
100  Cope with the differing wildcard and non-wildcard error cases.
101 ****************************************************************************/
102
103 static NTSTATUS determine_path_error(const char *name,
104                         bool allow_wcard_last_component,
105                         bool posix_pathnames)
106 {
107         const char *p;
108         bool name_has_wild = false;
109
110         if (!allow_wcard_last_component) {
111                 /* Error code within a pathname. */
112                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
113         }
114
115         /* We're terminating here so we
116          * can be a little slower and get
117          * the error code right. Windows
118          * treats the last part of the pathname
119          * separately I think, so if the last
120          * component is a wildcard then we treat
121          * this ./ as "end of component" */
122
123         p = strchr(name, '/');
124
125         if (!posix_pathnames) {
126                 name_has_wild = ms_has_wild(name);
127         }
128
129         if (!p && (name_has_wild || ISDOT(name))) {
130                 /* Error code at the end of a pathname. */
131                 return NT_STATUS_OBJECT_NAME_INVALID;
132         } else {
133                 /* Error code within a pathname. */
134                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
135         }
136 }
137
138 static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
139 {
140         /* Ensure we catch all names with in "/."
141            this is disallowed under Windows and
142            in POSIX they've already been removed. */
143         const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
144         if (p) {
145                 if (p[2] == '/') {
146                         /* Error code within a pathname. */
147                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
148                 } else if (p[2] == '\0') {
149                         /* Error code at the end of a pathname. */
150                         return NT_STATUS_OBJECT_NAME_INVALID;
151                 }
152         }
153         return NT_STATUS_OK;
154 }
155
156 /****************************************************************************
157  Optimization for common case where the missing part
158  is in the last component and the client already
159  sent the correct case.
160  Returns NT_STATUS_OK to mean continue the tree walk
161  (possibly with modified start pointer).
162  Any other NT_STATUS_XXX error means terminate the path
163  lookup here.
164 ****************************************************************************/
165
166 static NTSTATUS check_parent_exists(TALLOC_CTX *ctx,
167                                 connection_struct *conn,
168                                 bool posix_pathnames,
169                                 const struct smb_filename *smb_fname,
170                                 char **pp_dirpath,
171                                 char **pp_start,
172                                 int *p_parent_stat_errno)
173 {
174         char *parent_name = NULL;
175         struct smb_filename *parent_fname = NULL;
176         const char *last_component = NULL;
177         NTSTATUS status;
178         int ret;
179
180         if (!parent_dirname(ctx, smb_fname->base_name,
181                                 &parent_name,
182                                 &last_component)) {
183                 return NT_STATUS_NO_MEMORY;
184         }
185
186         if (!posix_pathnames) {
187                 if (ms_has_wild(parent_name)) {
188                         goto no_optimization_out;
189                 }
190         }
191
192         /*
193          * If there was no parent component in
194          * smb_fname->base_name then don't do this
195          * optimization.
196          */
197         if (smb_fname->base_name == last_component) {
198                 goto no_optimization_out;
199         }
200
201         parent_fname = synthetic_smb_fname(ctx,
202                                            parent_name,
203                                            NULL,
204                                            NULL,
205                                            smb_fname->twrp,
206                                            smb_fname->flags);
207         if (parent_fname == NULL) {
208                 return NT_STATUS_NO_MEMORY;
209         }
210
211         if (posix_pathnames) {
212                 ret = SMB_VFS_LSTAT(conn, parent_fname);
213         } else {
214                 ret = SMB_VFS_STAT(conn, parent_fname);
215         }
216
217         /* If the parent stat failed, just continue
218            with the normal tree walk. */
219
220         if (ret == -1) {
221                 /*
222                  * Optimization. Preserving the
223                  * errno from the STAT/LSTAT here
224                  * will allow us to save a duplicate
225                  * STAT/LSTAT system call of the parent
226                  * pathname in a hot code path in the caller.
227                  */
228                 if (p_parent_stat_errno != NULL) {
229                         *p_parent_stat_errno = errno;
230                 }
231                 goto no_optimization_out;
232         }
233
234         status = check_for_dot_component(parent_fname);
235         if (!NT_STATUS_IS_OK(status)) {
236                 return status;
237         }
238
239         /* Parent exists - set "start" to be the
240          * last component to shorten the tree walk. */
241
242         /*
243          * Safe to use discard_const_p
244          * here as last_component points
245          * into our smb_fname->base_name.
246          */
247         *pp_start = discard_const_p(char, last_component);
248
249         /* Update dirpath. */
250         TALLOC_FREE(*pp_dirpath);
251         *pp_dirpath = talloc_strdup(ctx, parent_fname->base_name);
252         if (!*pp_dirpath) {
253                 return NT_STATUS_NO_MEMORY;
254         }
255
256         DEBUG(5,("check_parent_exists: name "
257                 "= %s, dirpath = %s, "
258                 "start = %s\n",
259                 smb_fname->base_name,
260                 *pp_dirpath,
261                 *pp_start));
262
263         return NT_STATUS_OK;
264
265   no_optimization_out:
266
267         /*
268          * We must still return an *pp_dirpath
269          * initialized to ".", and a *pp_start
270          * pointing at smb_fname->base_name.
271          */
272
273         TALLOC_FREE(parent_name);
274         TALLOC_FREE(parent_fname);
275
276         *pp_dirpath = talloc_strdup(ctx, ".");
277         if (*pp_dirpath == NULL) {
278                 return NT_STATUS_NO_MEMORY;
279         }
280         /*
281          * Safe to use discard_const_p
282          * here as by convention smb_fname->base_name
283          * is allocated off ctx.
284          */
285         *pp_start = discard_const_p(char, smb_fname->base_name);
286         return NT_STATUS_OK;
287 }
288
289 /*
290  * Re-order a known good @GMT-token path.
291  */
292
293 static NTSTATUS rearrange_snapshot_path(struct smb_filename *smb_fname,
294                                 char *startp,
295                                 char *endp)
296 {
297         size_t endlen = 0;
298         size_t gmt_len = endp - startp;
299         char gmt_store[gmt_len + 1];
300         char *parent = NULL;
301         const char *last_component = NULL;
302         char *newstr;
303         bool ret;
304
305         DBG_DEBUG("|%s| -> ", smb_fname->base_name);
306
307         /* Save off the @GMT-token. */
308         memcpy(gmt_store, startp, gmt_len);
309         gmt_store[gmt_len] = '\0';
310
311         if (*endp == '/') {
312                 /* Remove any trailing '/' */
313                 endp++;
314         }
315
316         if (*endp == '\0') {
317                 /*
318                  * @GMT-token was at end of path.
319                  * Remove any preceding '/'
320                  */
321                 if (startp > smb_fname->base_name && startp[-1] == '/') {
322                         startp--;
323                 }
324         }
325
326         /* Remove @GMT-token from the path. */
327         endlen = strlen(endp);
328         memmove(startp, endp, endlen + 1);
329
330         /* Split the remaining path into components. */
331         ret = parent_dirname(smb_fname,
332                                 smb_fname->base_name,
333                                 &parent,
334                                 &last_component);
335         if (!ret) {
336                 /* Must terminate debug with \n */
337                 DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
338                 return NT_STATUS_NO_MEMORY;
339         }
340
341         if (ISDOT(parent)) {
342                 if (last_component[0] == '\0') {
343                         newstr = talloc_strdup(smb_fname,
344                                         gmt_store);
345                 } else {
346                         newstr = talloc_asprintf(smb_fname,
347                                         "%s/%s",
348                                         gmt_store,
349                                         last_component);
350                 }
351         } else {
352                 newstr = talloc_asprintf(smb_fname,
353                                         "%s/%s/%s",
354                                         gmt_store,
355                                         parent,
356                                         last_component);
357         }
358
359         TALLOC_FREE(parent);
360         TALLOC_FREE(smb_fname->base_name);
361         smb_fname->base_name = newstr;
362
363         DBG_DEBUG("|%s|\n", newstr);
364
365         return NT_STATUS_OK;
366 }
367
368 /*
369  * Strip a valid @GMT-token from any incoming filename path,
370  * adding any NTTIME encoded in the pathname into the
371  * twrp field of the passed in smb_fname.
372  *
373  * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
374  * at the *start* of a pathname component.
375  *
376  * If twrp is passed in then smb_fname->twrp is set to that
377  * value, and the @GMT-token part of the filename is removed
378  * and does not change the stored smb_fname->twrp.
379  *
380  */
381
382 NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
383                                     uint32_t ucf_flags,
384                                     NTTIME twrp)
385 {
386         char *startp = NULL;
387         char *endp = NULL;
388         char *tmp = NULL;
389         struct tm tm;
390         time_t t;
391         NTTIME nt;
392         NTSTATUS status;
393
394         if (twrp != 0) {
395                 smb_fname->twrp = twrp;
396         }
397
398         if (!(ucf_flags & UCF_GMT_PATHNAME)) {
399                 return NT_STATUS_OK;
400         }
401
402         startp = strchr_m(smb_fname->base_name, '@');
403         if (startp == NULL) {
404                 /* No @ */
405                 return NT_STATUS_OK;
406         }
407
408         startp = strstr_m(startp, "@GMT-");
409         if (startp == NULL) {
410                 /* No @ */
411                 return NT_STATUS_OK;
412         }
413
414         if ((startp > smb_fname->base_name) && (startp[-1] != '/')) {
415                 /* the GMT-token does not start a path-component */
416                 return NT_STATUS_OK;
417         }
418
419         endp = strptime(startp, GMT_FORMAT, &tm);
420         if (endp == NULL) {
421                 /* Not a valid timestring. */
422                 return NT_STATUS_OK;
423         }
424
425         if (endp[0] != '\0' && endp[0] != '/') {
426                 /*
427                  * It is not a complete path component, i.e. the path
428                  * component continues after the gmt-token.
429                  */
430                 return NT_STATUS_OK;
431         }
432
433         status = rearrange_snapshot_path(smb_fname, startp, endp);
434         if (!NT_STATUS_IS_OK(status)) {
435                 return status;
436         }
437
438         startp = smb_fname->base_name + GMT_NAME_LEN;
439         if (startp[0] == '/') {
440                 startp++;
441         }
442
443         tmp = talloc_strdup(smb_fname, startp);
444         if (tmp == NULL) {
445                 return NT_STATUS_NO_MEMORY;
446         }
447
448         TALLOC_FREE(smb_fname->base_name);
449         smb_fname->base_name = tmp;
450
451         if (smb_fname->twrp == 0) {
452                 tm.tm_isdst = -1;
453                 t = timegm(&tm);
454                 unix_to_nt_time(&nt, t);
455                 smb_fname->twrp = nt;
456         }
457
458         return NT_STATUS_OK;
459 }
460
461 /*
462  * Utility function to normalize case on an incoming client filename
463  * if required on this connection struct.
464  * Performs an in-place case conversion guaranteed to stay the same size.
465  */
466
467 static NTSTATUS normalize_filename_case(connection_struct *conn,
468                                         char *filename,
469                                         uint32_t ucf_flags)
470 {
471         bool ok;
472
473         if (ucf_flags & UCF_POSIX_PATHNAMES) {
474                 /*
475                  * POSIX never normalizes filename case.
476                  */
477                 return NT_STATUS_OK;
478         }
479         if (!conn->case_sensitive) {
480                 return NT_STATUS_OK;
481         }
482         if (conn->case_preserve) {
483                 return NT_STATUS_OK;
484         }
485         if (conn->short_case_preserve) {
486                 return NT_STATUS_OK;
487         }
488         ok = strnorm(filename, lp_default_case(SNUM(conn)));
489         if (!ok) {
490                 return NT_STATUS_INVALID_PARAMETER;
491         }
492         return NT_STATUS_OK;
493 }
494
495 /****************************************************************************
496 This routine is called to convert names from the dos namespace to unix
497 namespace. It needs to handle any case conversions, mangling, format changes,
498 streams etc.
499
500 We assume that we have already done a chdir() to the right "root" directory
501 for this service.
502
503 Conversion to basic unix format is already done in check_path_syntax().
504
505 Names must be relative to the root of the service - any leading /.  and
506 trailing /'s should have been trimmed by check_path_syntax().
507
508 The function will return an NTSTATUS error if some part of the name except for
509 the last part cannot be resolved, else NT_STATUS_OK.
510
511 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
512 didn't get any fatal errors that should immediately terminate the calling SMB
513 processing whilst resolving.
514
515 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard
516 should be allowed in the last component of the path only.
517
518 If the orig_path was a stream, smb_filename->base_name will point to the base
519 filename, and smb_filename->stream_name will point to the stream name.  If
520 orig_path was not a stream, then smb_filename->stream_name will be NULL.
521
522 On exit from unix_convert, the smb_filename->st stat struct will be populated
523 if the file exists and was found, if not this stat struct will be filled with
524 zeros (and this can be detected by checking for nlinks = 0, which can never be
525 true for any file).
526 ****************************************************************************/
527
528 struct uc_state {
529         TALLOC_CTX *mem_ctx;
530         struct connection_struct *conn;
531         struct smb_filename *smb_fname;
532         const char *orig_path;
533         uint32_t ucf_flags;
534         char *name;
535         char *end;
536         char *dirpath;
537         char *stream;
538         bool component_was_mangled;
539         bool name_has_wildcard;
540         bool posix_pathnames;
541         bool allow_wcard_last_component;
542         bool done;
543         bool case_sensitive;
544         bool case_preserve;
545         bool short_case_preserve;
546 };
547
548 static NTSTATUS unix_convert_step_search_fail(struct uc_state *state)
549 {
550         char *unmangled;
551
552         if (state->end) {
553                 /*
554                  * An intermediate part of the name
555                  * can't be found.
556                  */
557                 DBG_DEBUG("Intermediate [%s] missing\n",
558                           state->name);
559                 *state->end = '/';
560
561                 /*
562                  * We need to return the fact that the
563                  * intermediate name resolution failed.
564                  * This is used to return an error of
565                  * ERRbadpath rather than ERRbadfile.
566                  * Some Windows applications depend on
567                  * the difference between these two
568                  * errors.
569                  */
570
571                 /*
572                  * ENOENT, ENOTDIR and ELOOP all map
573                  * to NT_STATUS_OBJECT_PATH_NOT_FOUND
574                  * in the filename walk.
575                  */
576
577                 if (errno == ENOENT ||
578                     errno == ENOTDIR ||
579                     errno == ELOOP)
580                 {
581                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
582                 }
583                 return map_nt_error_from_unix(errno);
584         }
585
586         /*
587          * ENOENT/EACCESS are the only valid errors
588          * here.
589          */
590
591         if (errno == EACCES) {
592                 if ((state->ucf_flags & UCF_PREP_CREATEFILE) == 0) {
593                         return NT_STATUS_ACCESS_DENIED;
594                 } else {
595                         /*
596                          * This is the dropbox
597                          * behaviour. A dropbox is a
598                          * directory with only -wx
599                          * permissions, so
600                          * get_real_filename fails
601                          * with EACCESS, it needs to
602                          * list the directory. We
603                          * nevertheless want to allow
604                          * users creating a file.
605                          */
606                         errno = 0;
607                 }
608         }
609
610         if ((errno != 0) && (errno != ENOENT)) {
611                 /*
612                  * ENOTDIR and ELOOP both map to
613                  * NT_STATUS_OBJECT_PATH_NOT_FOUND
614                  * in the filename walk.
615                  */
616                 if (errno == ENOTDIR || errno == ELOOP) {
617                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
618                 }
619                 return map_nt_error_from_unix(errno);
620         }
621
622         /*
623          * POSIX pathnames must never call into mangling.
624          */
625         if (state->posix_pathnames) {
626                 goto done;
627         }
628
629         /*
630          * Just the last part of the name doesn't exist.
631          * We need to strupper() or strlower() it as
632          * this conversion may be used for file creation
633          * purposes. Fix inspired by
634          * Thomas Neumann <t.neumann@iku-ag.de>.
635          */
636         if (!state->case_preserve ||
637             (mangle_is_8_3(state->name, false,
638                            state->conn->params) &&
639              !state->short_case_preserve)) {
640                 if (!strnorm(state->name,
641                              lp_default_case(SNUM(state->conn)))) {
642                         DBG_DEBUG("strnorm %s failed\n",
643                                   state->name);
644                         return NT_STATUS_INVALID_PARAMETER;
645                 }
646         }
647
648         /*
649          * check on the mangled stack to see if we can
650          * recover the base of the filename.
651          */
652
653         if (mangle_is_mangled(state->name, state->conn->params)
654             && mangle_lookup_name_from_8_3(state->mem_ctx,
655                                            state->name,
656                                            &unmangled,
657                                            state->conn->params)) {
658                 char *tmp;
659                 size_t name_ofs =
660                         state->name - state->smb_fname->base_name;
661
662                 if (!ISDOT(state->dirpath)) {
663                         tmp = talloc_asprintf(
664                                 state->smb_fname, "%s/%s",
665                                 state->dirpath, unmangled);
666                         TALLOC_FREE(unmangled);
667                 }
668                 else {
669                         tmp = unmangled;
670                 }
671                 if (tmp == NULL) {
672                         DBG_ERR("talloc failed\n");
673                         return NT_STATUS_NO_MEMORY;
674                 }
675                 TALLOC_FREE(state->smb_fname->base_name);
676                 state->smb_fname->base_name = tmp;
677                 state->name =
678                         state->smb_fname->base_name + name_ofs;
679                 state->end = state->name + strlen(state->name);
680         }
681
682   done:
683
684         DBG_DEBUG("New file [%s]\n", state->name);
685         state->done = true;
686         return NT_STATUS_OK;
687 }
688
689 static NTSTATUS unix_convert_step_stat(struct uc_state *state)
690 {
691         struct smb_filename dname;
692         char dot[2] = ".";
693         char *found_name = NULL;
694         int ret;
695
696         /*
697          * Check if the name exists up to this point.
698          */
699
700         DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state->smb_fname));
701
702         ret = vfs_stat(state->conn, state->smb_fname);
703         if (ret == 0) {
704                 /*
705                  * It exists. it must either be a directory or this must
706                  * be the last part of the path for it to be OK.
707                  */
708                 if (state->end && !S_ISDIR(state->smb_fname->st.st_ex_mode)) {
709                         /*
710                          * An intermediate part of the name isn't
711                          * a directory.
712                          */
713                         DBG_DEBUG("Not a dir [%s]\n", state->name);
714                         *state->end = '/';
715                         /*
716                          * We need to return the fact that the
717                          * intermediate name resolution failed. This
718                          * is used to return an error of ERRbadpath
719                          * rather than ERRbadfile. Some Windows
720                          * applications depend on the difference between
721                          * these two errors.
722                          */
723                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
724                 }
725                 return NT_STATUS_OK;
726         }
727
728         /* Stat failed - ensure we don't use it. */
729         SET_STAT_INVALID(state->smb_fname->st);
730
731         if (state->posix_pathnames) {
732                 /*
733                  * For posix_pathnames, we're done.
734                  * Don't blunder into the name_has_wildcard OR
735                  * get_real_filename() codepaths as they may
736                  * be doing case insensitive lookups. So when
737                  * creating a new POSIX directory Foo they might
738                  * match on name foo.
739                  *
740                  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
741                  */
742                 if (state->end != NULL) {
743                         const char *morepath = NULL;
744                         /*
745                          * If this is intermediate we must
746                          * restore the full path.
747                          */
748                         *state->end = '/';
749                         /*
750                          * If there are any more components
751                          * after the failed LSTAT we cannot
752                          * continue.
753                          */
754                         morepath = strchr(state->end + 1, '/');
755                         if (morepath != NULL) {
756                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
757                         }
758                 }
759                 if (errno == ENOENT) {
760                         /* New file or directory. */
761                         state->done = true;
762                         return NT_STATUS_OK;
763                 }
764                 if ((errno == EACCES) &&
765                     (state->ucf_flags & UCF_PREP_CREATEFILE)) {
766                         /* POSIX Dropbox case. */
767                         errno = 0;
768                         state->done = true;
769                         return NT_STATUS_OK;
770                 }
771                 return map_nt_error_from_unix(errno);
772         }
773
774         /*
775          * Reset errno so we can detect
776          * directory open errors.
777          */
778         errno = 0;
779
780         /*
781          * Try to find this part of the path in the directory.
782          */
783
784         if (state->name_has_wildcard) {
785                 return unix_convert_step_search_fail(state);
786         }
787
788         dname = (struct smb_filename) {
789                 .base_name = state->dirpath,
790                 .twrp = state->smb_fname->twrp,
791         };
792
793         /* handle null paths */
794         if ((dname.base_name == NULL) || (dname.base_name[0] == '\0')) {
795                 dname.base_name = dot;
796         }
797
798         ret = get_real_filename(state->conn,
799                                 &dname,
800                                 state->name,
801                                 talloc_tos(),
802                                 &found_name);
803         if (ret != 0) {
804                 return unix_convert_step_search_fail(state);
805         }
806
807         /*
808          * Restore the rest of the string. If the string was
809          * mangled the size may have changed.
810          */
811         if (state->end) {
812                 char *tmp;
813                 size_t name_ofs =
814                         state->name - state->smb_fname->base_name;
815
816                 if (!ISDOT(state->dirpath)) {
817                         tmp = talloc_asprintf(state->smb_fname,
818                                               "%s/%s/%s", state->dirpath,
819                                               found_name, state->end+1);
820                 }
821                 else {
822                         tmp = talloc_asprintf(state->smb_fname,
823                                               "%s/%s", found_name,
824                                               state->end+1);
825                 }
826                 if (tmp == NULL) {
827                         DBG_ERR("talloc_asprintf failed\n");
828                         return NT_STATUS_NO_MEMORY;
829                 }
830                 TALLOC_FREE(state->smb_fname->base_name);
831                 state->smb_fname->base_name = tmp;
832                 state->name = state->smb_fname->base_name + name_ofs;
833                 state->end = state->name + strlen(found_name);
834                 *state->end = '\0';
835         } else {
836                 char *tmp;
837                 size_t name_ofs =
838                         state->name - state->smb_fname->base_name;
839
840                 if (!ISDOT(state->dirpath)) {
841                         tmp = talloc_asprintf(state->smb_fname,
842                                               "%s/%s", state->dirpath,
843                                               found_name);
844                 } else {
845                         tmp = talloc_strdup(state->smb_fname,
846                                             found_name);
847                 }
848                 if (tmp == NULL) {
849                         DBG_ERR("talloc failed\n");
850                         return NT_STATUS_NO_MEMORY;
851                 }
852                 TALLOC_FREE(state->smb_fname->base_name);
853                 state->smb_fname->base_name = tmp;
854                 state->name = state->smb_fname->base_name + name_ofs;
855
856                 /*
857                  * We just scanned for, and found the end of
858                  * the path. We must return a valid stat struct
859                  * if it exists. JRA.
860                  */
861
862                 ret = vfs_stat(state->conn, state->smb_fname);
863                 if (ret != 0) {
864                         SET_STAT_INVALID(state->smb_fname->st);
865                 }
866         }
867
868         TALLOC_FREE(found_name);
869         return NT_STATUS_OK;
870 }
871
872 static NTSTATUS unix_convert_step(struct uc_state *state)
873 {
874         NTSTATUS status;
875
876         /*
877          * Pinpoint the end of this section of the filename.
878          */
879         /* mb safe. '/' can't be in any encoded char. */
880         state->end = strchr(state->name, '/');
881
882         /*
883          * Chop the name at this point.
884          */
885         if (state->end != NULL) {
886                 *state->end = 0;
887         }
888
889         DBG_DEBUG("dirpath [%s] name [%s]\n", state->dirpath, state->name);
890
891         /* The name cannot have a component of "." */
892
893         if (ISDOT(state->name)) {
894                 if (state->end == NULL)  {
895                         /* Error code at the end of a pathname. */
896                         return NT_STATUS_OBJECT_NAME_INVALID;
897                 }
898                 return determine_path_error(state->end+1,
899                                             state->allow_wcard_last_component,
900                                             state->posix_pathnames);
901         }
902
903         /* The name cannot have a wildcard if it's not
904            the last component. */
905
906         if (!state->posix_pathnames) {
907                 state->name_has_wildcard = ms_has_wild(state->name);
908         }
909
910         /* Wildcards never valid within a pathname. */
911         if (state->name_has_wildcard && state->end != NULL) {
912                 return NT_STATUS_OBJECT_NAME_INVALID;
913         }
914
915         /* Skip the stat call if it's a wildcard end. */
916         if (state->name_has_wildcard) {
917                 DBG_DEBUG("Wildcard [%s]\n", state->name);
918                 state->done = true;
919                 return NT_STATUS_OK;
920         }
921
922         status = unix_convert_step_stat(state);
923         if (!NT_STATUS_IS_OK(status)) {
924                 return status;
925         }
926         if (state->done) {
927                 return NT_STATUS_OK;
928         }
929
930         /*
931          * Add to the dirpath that we have resolved so far.
932          */
933
934         if (!ISDOT(state->dirpath)) {
935                 char *tmp = talloc_asprintf(state->mem_ctx,
936                                             "%s/%s", state->dirpath, state->name);
937                 if (!tmp) {
938                         DBG_ERR("talloc_asprintf failed\n");
939                         return NT_STATUS_NO_MEMORY;
940                 }
941                 TALLOC_FREE(state->dirpath);
942                 state->dirpath = tmp;
943         }
944         else {
945                 TALLOC_FREE(state->dirpath);
946                 if (!(state->dirpath = talloc_strdup(state->mem_ctx,state->name))) {
947                         DBG_ERR("talloc_strdup failed\n");
948                         return NT_STATUS_NO_MEMORY;
949                 }
950         }
951
952         /*
953          * Cache the dirpath thus far. Don't cache a name with mangled
954          * or wildcard components as this can change the size.
955          */
956         if(!state->component_was_mangled && !state->name_has_wildcard) {
957                 stat_cache_add(state->orig_path,
958                                state->dirpath,
959                                state->smb_fname->twrp,
960                                state->case_sensitive);
961         }
962
963         /*
964          * Restore the / that we wiped out earlier.
965          */
966         if (state->end != NULL) {
967                 *state->end = '/';
968         }
969
970         return NT_STATUS_OK;
971 }
972
973 NTSTATUS unix_convert(TALLOC_CTX *mem_ctx,
974                       connection_struct *conn,
975                       const char *orig_path,
976                       NTTIME twrp,
977                       struct smb_filename **smb_fname_out,
978                       uint32_t ucf_flags)
979 {
980         struct uc_state uc_state;
981         struct uc_state *state = &uc_state;
982         NTSTATUS status;
983         int ret = -1;
984
985         *state = (struct uc_state) {
986                 .mem_ctx = mem_ctx,
987                 .conn = conn,
988                 .orig_path = orig_path,
989                 .ucf_flags = ucf_flags,
990                 .posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES),
991                 .allow_wcard_last_component = (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP),
992                 .case_sensitive = conn->case_sensitive,
993                 .case_preserve = conn->case_preserve,
994                 .short_case_preserve = conn->short_case_preserve,
995         };
996
997         *smb_fname_out = NULL;
998
999         if (state->posix_pathnames) {
1000                 /* POSIX means ignore case settings on share. */
1001                 state->case_sensitive = true;
1002                 state->case_preserve = true;
1003                 state->short_case_preserve = true;
1004         }
1005
1006         state->smb_fname = talloc_zero(state->mem_ctx, struct smb_filename);
1007         if (state->smb_fname == NULL) {
1008                 return NT_STATUS_NO_MEMORY;
1009         }
1010
1011         if (state->conn->printer) {
1012                 /* we don't ever use the filenames on a printer share as a
1013                         filename - so don't convert them */
1014                 state->smb_fname->base_name = talloc_strdup(
1015                         state->smb_fname, state->orig_path);
1016                 if (state->smb_fname->base_name == NULL) {
1017                         status = NT_STATUS_NO_MEMORY;
1018                         goto err;
1019                 }
1020                 goto done;
1021         }
1022
1023         state->smb_fname->flags = state->posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0;
1024
1025         DBG_DEBUG("Called on file [%s]\n", state->orig_path);
1026
1027         if (state->orig_path[0] == '/') {
1028                 DBG_ERR("Path [%s] starts with '/'\n", state->orig_path);
1029                 return NT_STATUS_OBJECT_NAME_INVALID;
1030         }
1031
1032         /* Start with the full orig_path as given by the caller. */
1033         state->smb_fname->base_name = talloc_strdup(
1034                 state->smb_fname, state->orig_path);
1035         if (state->smb_fname->base_name == NULL) {
1036                 DBG_ERR("talloc_strdup failed\n");
1037                 status = NT_STATUS_NO_MEMORY;
1038                 goto err;
1039         }
1040
1041         /* Canonicalize any @GMT- paths. */
1042         status = canonicalize_snapshot_path(state->smb_fname, ucf_flags, twrp);
1043         if (!NT_STATUS_IS_OK(status)) {
1044                 goto err;
1045         }
1046
1047         /*
1048          * If we trimmed down to a single '\0' character
1049          * then we should use the "." directory to avoid
1050          * searching the cache, but not if we are in a
1051          * printing share.
1052          * As we know this is valid we can return true here.
1053          */
1054
1055         if (state->smb_fname->base_name[0] == '\0') {
1056                 state->smb_fname->base_name = talloc_strdup(state->smb_fname, ".");
1057                 if (state->smb_fname->base_name == NULL) {
1058                         status = NT_STATUS_NO_MEMORY;
1059                         goto err;
1060                 }
1061                 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
1062                         status = map_nt_error_from_unix(errno);
1063                         goto err;
1064                 }
1065                 DBG_DEBUG("conversion finished [] -> [%s]\n",
1066                           state->smb_fname->base_name);
1067                 goto done;
1068         }
1069
1070         if (state->orig_path[0] == '.' && (state->orig_path[1] == '/' ||
1071                                 state->orig_path[1] == '\0')) {
1072                 /* Start of pathname can't be "." only. */
1073                 if (state->orig_path[1] == '\0' || state->orig_path[2] == '\0') {
1074                         status = NT_STATUS_OBJECT_NAME_INVALID;
1075                 } else {
1076                         status =determine_path_error(&state->orig_path[2],
1077                             state->allow_wcard_last_component,
1078                             state->posix_pathnames);
1079                 }
1080                 goto err;
1081         }
1082
1083         /*
1084          * Large directory fix normalization. If we're case sensitive, and
1085          * the case preserving parameters are set to "no", normalize the case of
1086          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
1087          * This is in conflict with the current (3.0.20) man page, but is
1088          * what people expect from the "large directory howto". I'll update
1089          * the man page. Thanks to jht@samba.org for finding this. JRA.
1090          */
1091
1092         status = normalize_filename_case(state->conn,
1093                                          state->smb_fname->base_name,
1094                                          ucf_flags);
1095         if (!NT_STATUS_IS_OK(status)) {
1096                 DBG_ERR("normalize_filename_case %s failed\n",
1097                                 state->smb_fname->base_name);
1098                 goto err;
1099         }
1100
1101         /*
1102          * Strip off the stream, and add it back when we're done with the
1103          * base_name.
1104          */
1105         if (!state->posix_pathnames) {
1106                 state->stream = strchr_m(state->smb_fname->base_name, ':');
1107
1108                 if (state->stream != NULL) {
1109                         char *tmp = talloc_strdup(state->smb_fname, state->stream);
1110                         if (tmp == NULL) {
1111                                 status = NT_STATUS_NO_MEMORY;
1112                                 goto err;
1113                         }
1114                         /*
1115                          * Since this is actually pointing into
1116                          * smb_fname->base_name this truncates base_name.
1117                          */
1118                         *state->stream = '\0';
1119                         state->stream = tmp;
1120
1121                         if (state->smb_fname->base_name[0] == '\0') {
1122                                 /*
1123                                  * orig_name was just a stream name.
1124                                  * This is a stream on the root of
1125                                  * the share. Replace base_name with
1126                                  * a "."
1127                                  */
1128                                 state->smb_fname->base_name =
1129                                         talloc_strdup(state->smb_fname, ".");
1130                                 if (state->smb_fname->base_name == NULL) {
1131                                         status = NT_STATUS_NO_MEMORY;
1132                                         goto err;
1133                                 }
1134                                 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
1135                                         status = map_nt_error_from_unix(errno);
1136                                         goto err;
1137                                 }
1138                                 /* dirpath must exist. */
1139                                 state->dirpath = talloc_strdup(state->mem_ctx,".");
1140                                 if (state->dirpath == NULL) {
1141                                         status = NT_STATUS_NO_MEMORY;
1142                                         goto err;
1143                                 }
1144                                 DBG_INFO("conversion finished [%s] -> [%s]\n",
1145                                          state->orig_path,
1146                                          state->smb_fname->base_name);
1147                                 goto done;
1148                         }
1149                 }
1150         }
1151
1152         state->name = state->smb_fname->base_name;
1153
1154         /*
1155          * If we're providing case insensitive semantics or
1156          * the underlying filesystem is case insensitive,
1157          * then a case-normalized hit in the stat-cache is
1158          * authoritative. JRA.
1159          *
1160          * Note: We're only checking base_name.  The stream_name will be
1161          * added and verified in build_stream_path().
1162          */
1163
1164         if (!state->case_sensitive ||
1165             !(state->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
1166         {
1167                 bool found;
1168
1169                 found = stat_cache_lookup(state->conn,
1170                                           state->posix_pathnames,
1171                                           &state->smb_fname->base_name,
1172                                           &state->dirpath,
1173                                           &state->name,
1174                                           state->smb_fname->twrp,
1175                                           &state->smb_fname->st);
1176                 if (found) {
1177                         goto done;
1178                 }
1179         }
1180
1181         /*
1182          * Make sure "dirpath" is an allocated string, we use this for
1183          * building the directories with talloc_asprintf and free it.
1184          */
1185
1186         if (state->dirpath == NULL) {
1187                 state->dirpath = talloc_strdup(state->mem_ctx,".");
1188                 if (state->dirpath == NULL) {
1189                         DBG_ERR("talloc_strdup failed\n");
1190                         status = NT_STATUS_NO_MEMORY;
1191                         goto err;
1192                 }
1193         }
1194
1195         /*
1196          * If we have a wildcard we must walk the path to
1197          * find where the error is, even if case sensitive
1198          * is true.
1199          */
1200
1201         if (!state->posix_pathnames) {
1202                 /* POSIX pathnames have no wildcards. */
1203                 state->name_has_wildcard = ms_has_wild(state->smb_fname->base_name);
1204                 if (state->name_has_wildcard && !state->allow_wcard_last_component) {
1205                         /* Wildcard not valid anywhere. */
1206                         status = NT_STATUS_OBJECT_NAME_INVALID;
1207                         goto fail;
1208                 }
1209         }
1210
1211         DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
1212                   state->smb_fname->base_name, state->dirpath, state->name);
1213
1214         if (!state->name_has_wildcard) {
1215                 int parent_stat_errno = 0;
1216
1217                 /*
1218                  * stat the name - if it exists then we can add the stream back (if
1219                  * there was one) and be done!
1220                  */
1221
1222                 ret = vfs_stat(state->conn, state->smb_fname);
1223                 if (ret == 0) {
1224                         status = check_for_dot_component(state->smb_fname);
1225                         if (!NT_STATUS_IS_OK(status)) {
1226                                 goto fail;
1227                         }
1228                         /* Add the path (not including the stream) to the cache. */
1229                         stat_cache_add(state->orig_path,
1230                                        state->smb_fname->base_name,
1231                                        state->smb_fname->twrp,
1232                                        state->case_sensitive);
1233                         DBG_DEBUG("Conversion of base_name finished "
1234                                   "[%s] -> [%s]\n",
1235                                   state->orig_path, state->smb_fname->base_name);
1236                         goto done;
1237                 }
1238
1239                 /* Stat failed - ensure we don't use it. */
1240                 SET_STAT_INVALID(state->smb_fname->st);
1241
1242                 /*
1243                  * Note: we must continue processing a path if we get EACCES
1244                  * from stat. With NFS4 permissions the file might be lacking
1245                  * READ_ATTR, but if the parent has LIST permissions we can
1246                  * resolve the path in the path traversal loop down below.
1247                  */
1248
1249                 if (errno == ENOENT) {
1250                         /* Optimization when creating a new file - only
1251                            the last component doesn't exist.
1252                            NOTE : check_parent_exists() doesn't preserve errno.
1253                         */
1254                         int saved_errno = errno;
1255                         status = check_parent_exists(state->mem_ctx,
1256                                                 state->conn,
1257                                                 state->posix_pathnames,
1258                                                 state->smb_fname,
1259                                                 &state->dirpath,
1260                                                 &state->name,
1261                                                 &parent_stat_errno);
1262                         errno = saved_errno;
1263                         if (!NT_STATUS_IS_OK(status)) {
1264                                 goto fail;
1265                         }
1266                 }
1267
1268                 /*
1269                  * A special case - if we don't have any wildcards or mangling chars and are case
1270                  * sensitive or the underlying filesystem is case insensitive then searching
1271                  * won't help.
1272                  *
1273                  * NB. As POSIX sets state->case_sensitive as
1274                  * true we will never call into mangle_is_mangled() here.
1275                  */
1276
1277                 if ((state->case_sensitive || !(state->conn->fs_capabilities &
1278                                         FILE_CASE_SENSITIVE_SEARCH)) &&
1279                                 !mangle_is_mangled(state->smb_fname->base_name, state->conn->params)) {
1280
1281                         status = check_for_dot_component(state->smb_fname);
1282                         if (!NT_STATUS_IS_OK(status)) {
1283                                 goto fail;
1284                         }
1285
1286                         /*
1287                          * The stat failed. Could be ok as it could be
1288                          * a new file.
1289                          */
1290
1291                         if (errno == ENOTDIR || errno == ELOOP) {
1292                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1293                                 goto fail;
1294                         } else if (errno == ENOENT) {
1295                                 /*
1296                                  * Was it a missing last component ?
1297                                  * or a missing intermediate component ?
1298                                  *
1299                                  * Optimization.
1300                                  *
1301                                  * For this code path we can guarantee that
1302                                  * we have gone through check_parent_exists()
1303                                  * and it returned NT_STATUS_OK.
1304                                  *
1305                                  * Either there was no parent component (".")
1306                                  * parent_stat_errno == 0 and we have a missing
1307                                  * last component here.
1308                                  *
1309                                  * OR check_parent_exists() called STAT/LSTAT
1310                                  * and if it failed parent_stat_errno has been
1311                                  * set telling us if the parent existed or not.
1312                                  *
1313                                  * Either way we can avoid another STAT/LSTAT
1314                                  * system call on the parent here.
1315                                  */
1316                                 if (parent_stat_errno == ENOTDIR ||
1317                                                 parent_stat_errno == ENOENT ||
1318                                                 parent_stat_errno == ELOOP) {
1319                                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1320                                         goto fail;
1321                                 }
1322
1323                                 /*
1324                                  * Missing last component is ok - new file.
1325                                  * Also deal with permission denied elsewhere.
1326                                  * Just drop out to done.
1327                                  */
1328                                 goto done;
1329                         }
1330                 }
1331         } else {
1332                 /*
1333                  * We have a wildcard in the pathname.
1334                  *
1335                  * Optimization for common case where the wildcard
1336                  * is in the last component and the client already
1337                  * sent the correct case.
1338                  * NOTE : check_parent_exists() doesn't preserve errno.
1339                  */
1340                 int saved_errno = errno;
1341                 status = check_parent_exists(state->mem_ctx,
1342                                         state->conn,
1343                                         state->posix_pathnames,
1344                                         state->smb_fname,
1345                                         &state->dirpath,
1346                                         &state->name,
1347                                         NULL);
1348                 errno = saved_errno;
1349                 if (!NT_STATUS_IS_OK(status)) {
1350                         goto fail;
1351                 }
1352         }
1353
1354         /*
1355          * is_mangled() was changed to look at an entire pathname, not
1356          * just a component. JRA.
1357          */
1358
1359         if (state->posix_pathnames) {
1360                 /*
1361                  * POSIX names are never mangled and we must not
1362                  * call into mangling functions.
1363                  */
1364                 state->component_was_mangled = false;
1365         } else if (mangle_is_mangled(state->name, state->conn->params)) {
1366                 state->component_was_mangled = true;
1367         }
1368
1369         /*
1370          * Now we need to recursively match the name against the real
1371          * directory structure.
1372          */
1373
1374         /*
1375          * Match each part of the path name separately, trying the names
1376          * as is first, then trying to scan the directory for matching names.
1377          */
1378
1379         for (; state->name ; state->name = (state->end ? state->end + 1:(char *)NULL)) {
1380                 status = unix_convert_step(state);
1381                 if (!NT_STATUS_IS_OK(status)) {
1382                         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1383                                 goto err;
1384                         }
1385                         goto fail;
1386                 }
1387                 if (state->done) {
1388                         goto done;
1389                 }
1390         }
1391
1392         /*
1393          * Cache the full path. Don't cache a name with mangled or wildcard
1394          * components as this can change the size.
1395          */
1396
1397         if(!state->component_was_mangled && !state->name_has_wildcard) {
1398                 stat_cache_add(state->orig_path,
1399                                state->smb_fname->base_name,
1400                                state->smb_fname->twrp,
1401                                state->case_sensitive);
1402         }
1403
1404         /*
1405          * The name has been resolved.
1406          */
1407
1408  done:
1409         /* Add back the stream if one was stripped off originally. */
1410         if (state->stream != NULL) {
1411                 state->smb_fname->stream_name = state->stream;
1412
1413                 /* Check path now that the base_name has been converted. */
1414                 status = build_stream_path(state->mem_ctx, state->conn, state->smb_fname);
1415                 if (!NT_STATUS_IS_OK(status)) {
1416                         goto fail;
1417                 }
1418         }
1419
1420         DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
1421                    state->orig_path, smb_fname_str_dbg(state->smb_fname));
1422
1423         TALLOC_FREE(state->dirpath);
1424         *smb_fname_out = state->smb_fname;
1425         return NT_STATUS_OK;
1426  fail:
1427         DBG_DEBUG("Conversion failed: dirpath [%s] name [%s]\n",
1428                   state->dirpath, state->name);
1429         if ((state->dirpath != NULL) && !ISDOT(state->dirpath)) {
1430                 state->smb_fname->base_name = talloc_asprintf(
1431                         state->smb_fname,
1432                         "%s/%s",
1433                         state->dirpath,
1434                         state->name);
1435         } else {
1436                 state->smb_fname->base_name = talloc_strdup(
1437                         state->smb_fname, state->name);
1438         }
1439         if (state->smb_fname->base_name == NULL) {
1440                 DBG_ERR("talloc_asprintf failed\n");
1441                 status = NT_STATUS_NO_MEMORY;
1442                 goto err;
1443         }
1444
1445         *smb_fname_out = state->smb_fname;
1446         TALLOC_FREE(state->dirpath);
1447         return status;
1448  err:
1449         TALLOC_FREE(state->smb_fname);
1450         return status;
1451 }
1452
1453 /****************************************************************************
1454  Ensure a path is not vetoed.
1455 ****************************************************************************/
1456
1457 static NTSTATUS check_veto_path(connection_struct *conn,
1458                         const struct smb_filename *smb_fname)
1459 {
1460         const char *name = smb_fname->base_name;
1461
1462         if (IS_VETO_PATH(conn, name))  {
1463                 /* Is it not dot or dot dot. */
1464                 if (!(ISDOT(name) || ISDOTDOT(name))) {
1465                         DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1466                                                 name));
1467                         return map_nt_error_from_unix(ENOENT);
1468                 }
1469         }
1470         return NT_STATUS_OK;
1471 }
1472
1473 /****************************************************************************
1474  Check a filename - possibly calling check_reduced_name.
1475  This is called by every routine before it allows an operation on a filename.
1476  It does any final confirmation necessary to ensure that the filename is
1477  a valid one for the user to access.
1478 ****************************************************************************/
1479
1480 static NTSTATUS check_name(connection_struct *conn,
1481                         const struct smb_filename *smb_fname)
1482 {
1483         NTSTATUS status = check_veto_path(conn, smb_fname);
1484
1485         if (!NT_STATUS_IS_OK(status)) {
1486                 return status;
1487         }
1488
1489         if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
1490                 status = check_reduced_name(conn, NULL, smb_fname);
1491                 if (!NT_STATUS_IS_OK(status)) {
1492                         DEBUG(5,("check_name: name %s failed with %s\n",
1493                                         smb_fname->base_name,
1494                                         nt_errstr(status)));
1495                         return status;
1496                 }
1497         }
1498
1499         return NT_STATUS_OK;
1500 }
1501
1502 /****************************************************************************
1503  Check if two filenames are equal.
1504  This needs to be careful about whether we are case sensitive.
1505 ****************************************************************************/
1506
1507 static bool fname_equal(const char *name1, const char *name2,
1508                 bool case_sensitive)
1509 {
1510         /* Normal filename handling */
1511         if (case_sensitive) {
1512                 return(strcmp(name1,name2) == 0);
1513         }
1514
1515         return(strequal(name1,name2));
1516 }
1517
1518 static bool sname_equal(const char *name1, const char *name2,
1519                 bool case_sensitive)
1520 {
1521         bool match;
1522         const char *s1 = NULL;
1523         const char *s2 = NULL;
1524         size_t n1;
1525         size_t n2;
1526         const char *e1 = NULL;
1527         const char *e2 = NULL;
1528         char *c1 = NULL;
1529         char *c2 = NULL;
1530
1531         match = fname_equal(name1, name2, case_sensitive);
1532         if (match) {
1533                 return true;
1534         }
1535
1536         if (name1[0] != ':') {
1537                 return false;
1538         }
1539         if (name2[0] != ':') {
1540                 return false;
1541         }
1542         s1 = &name1[1];
1543         e1 = strchr(s1, ':');
1544         if (e1 == NULL) {
1545                 n1 = strlen(s1);
1546         } else {
1547                 n1 = PTR_DIFF(e1, s1);
1548         }
1549         s2 = &name2[1];
1550         e2 = strchr(s2, ':');
1551         if (e2 == NULL) {
1552                 n2 = strlen(s2);
1553         } else {
1554                 n2 = PTR_DIFF(e2, s2);
1555         }
1556
1557         /* Normal filename handling */
1558         if (case_sensitive) {
1559                 return (strncmp(s1, s2, n1) == 0);
1560         }
1561
1562         /*
1563          * We can't use strnequal() here
1564          * as it takes the number of codepoints
1565          * and not the number of bytes.
1566          *
1567          * So we make a copy before calling
1568          * strequal().
1569          *
1570          * Note that we TALLOC_FREE() in reverse order
1571          * in order to avoid memory fragmentation.
1572          */
1573
1574         c1 = talloc_strndup(talloc_tos(), s1, n1);
1575         c2 = talloc_strndup(talloc_tos(), s2, n2);
1576         if (c1 == NULL || c2 == NULL) {
1577                 TALLOC_FREE(c2);
1578                 TALLOC_FREE(c1);
1579                 return (strncmp(s1, s2, n1) == 0);
1580         }
1581
1582         match = strequal(c1, c2);
1583         TALLOC_FREE(c2);
1584         TALLOC_FREE(c1);
1585         return match;
1586 }
1587
1588 /****************************************************************************
1589  Scan a directory to find a filename, matching without case sensitivity.
1590  If the name looks like a mangled name then try via the mangling functions
1591 ****************************************************************************/
1592
1593 int get_real_filename_full_scan(connection_struct *conn,
1594                                 const char *path,
1595                                 const char *name,
1596                                 bool mangled,
1597                                 TALLOC_CTX *mem_ctx,
1598                                 char **found_name)
1599 {
1600         struct smb_Dir *cur_dir;
1601         const char *dname = NULL;
1602         char *talloced = NULL;
1603         char *unmangled_name = NULL;
1604         long curpos;
1605         struct smb_filename *smb_fname = NULL;
1606
1607         /* handle null paths */
1608         if ((path == NULL) || (*path == 0)) {
1609                 path = ".";
1610         }
1611
1612         /* If we have a case-sensitive filesystem, it doesn't do us any
1613          * good to search for a name. If a case variation of the name was
1614          * there, then the original stat(2) would have found it.
1615          */
1616         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
1617                 errno = ENOENT;
1618                 return -1;
1619         }
1620
1621         /*
1622          * The incoming name can be mangled, and if we de-mangle it
1623          * here it will not compare correctly against the filename (name2)
1624          * read from the directory and then mangled by the name_to_8_3()
1625          * call. We need to mangle both names or neither.
1626          * (JRA).
1627          *
1628          * Fix for bug found by Dina Fine. If in case sensitive mode then
1629          * the mangle cache is no good (3 letter extension could be wrong
1630          * case - so don't demangle in this case - leave as mangled and
1631          * allow the mangling of the directory entry read (which is done
1632          * case insensitively) to match instead. This will lead to more
1633          * false positive matches but we fail completely without it. JRA.
1634          */
1635
1636         if (mangled && !conn->case_sensitive) {
1637                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
1638                                                        &unmangled_name,
1639                                                        conn->params);
1640                 if (!mangled) {
1641                         /* Name is now unmangled. */
1642                         name = unmangled_name;
1643                 }
1644         }
1645
1646         smb_fname = synthetic_smb_fname(talloc_tos(),
1647                                         path,
1648                                         NULL,
1649                                         NULL,
1650                                         0,
1651                                         0);
1652         if (smb_fname == NULL) {
1653                 TALLOC_FREE(unmangled_name);
1654                 return -1;
1655         }
1656
1657         /* open the directory */
1658         if (!(cur_dir = OpenDir(talloc_tos(), conn, smb_fname, NULL, 0))) {
1659                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
1660                 TALLOC_FREE(unmangled_name);
1661                 TALLOC_FREE(smb_fname);
1662                 return -1;
1663         }
1664
1665         TALLOC_FREE(smb_fname);
1666
1667         /* now scan for matching names */
1668         curpos = 0;
1669         while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
1670
1671                 /* Is it dot or dot dot. */
1672                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1673                         TALLOC_FREE(talloced);
1674                         continue;
1675                 }
1676
1677                 /*
1678                  * At this point dname is the unmangled name.
1679                  * name is either mangled or not, depending on the state
1680                  * of the "mangled" variable. JRA.
1681                  */
1682
1683                 /*
1684                  * Check mangled name against mangled name, or unmangled name
1685                  * against unmangled name.
1686                  */
1687
1688                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
1689                         fname_equal(name, dname, conn->case_sensitive)) {
1690                         /* we've found the file, change it's name and return */
1691                         *found_name = talloc_strdup(mem_ctx, dname);
1692                         TALLOC_FREE(unmangled_name);
1693                         TALLOC_FREE(cur_dir);
1694                         if (!*found_name) {
1695                                 errno = ENOMEM;
1696                                 TALLOC_FREE(talloced);
1697                                 return -1;
1698                         }
1699                         TALLOC_FREE(talloced);
1700                         return 0;
1701                 }
1702                 TALLOC_FREE(talloced);
1703         }
1704
1705         TALLOC_FREE(unmangled_name);
1706         TALLOC_FREE(cur_dir);
1707         errno = ENOENT;
1708         return -1;
1709 }
1710
1711 /****************************************************************************
1712  Wrapper around the vfs get_real_filename and the full directory scan
1713  fallback.
1714 ****************************************************************************/
1715
1716 static int get_real_filename(connection_struct *conn,
1717                              struct smb_filename *path,
1718                              const char *name,
1719                              TALLOC_CTX *mem_ctx,
1720                              char **found_name)
1721 {
1722         int ret;
1723         bool mangled;
1724
1725         mangled = mangle_is_mangled(name, conn->params);
1726
1727         if (mangled) {
1728                 return get_real_filename_full_scan(conn,
1729                                                    path->base_name,
1730                                                    name,
1731                                                    mangled,
1732                                                    mem_ctx,
1733                                                    found_name);
1734         }
1735
1736         /* Try the vfs first to take advantage of case-insensitive stat. */
1737         ret = SMB_VFS_GET_REAL_FILENAME(conn,
1738                                         path,
1739                                         name,
1740                                         mem_ctx,
1741                                         found_name);
1742
1743         /*
1744          * If the case-insensitive stat was successful, or returned an error
1745          * other than EOPNOTSUPP then there is no need to fall back on the
1746          * full directory scan.
1747          */
1748         if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
1749                 return ret;
1750         }
1751
1752         return get_real_filename_full_scan(conn,
1753                                            path->base_name,
1754                                            name,
1755                                            mangled,
1756                                            mem_ctx,
1757                                            found_name);
1758 }
1759
1760 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1761                                   connection_struct *conn,
1762                                   struct smb_filename *smb_fname)
1763 {
1764         NTSTATUS status;
1765         unsigned int i, num_streams = 0;
1766         struct stream_struct *streams = NULL;
1767         struct smb_filename *pathref = NULL;
1768
1769         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1770                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1771                 return NT_STATUS_OK;
1772         }
1773
1774         if (errno != ENOENT) {
1775                 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1776                 status = map_nt_error_from_unix(errno);
1777                 goto fail;
1778         }
1779
1780         if (smb_fname->fsp == NULL) {
1781                 status = synthetic_pathref(mem_ctx,
1782                                         conn->cwd_fsp,
1783                                         smb_fname->base_name,
1784                                         NULL,
1785                                         NULL,
1786                                         smb_fname->twrp,
1787                                         smb_fname->flags,
1788                                         &pathref);
1789                 if (!NT_STATUS_IS_OK(status)) {
1790                         if (NT_STATUS_EQUAL(status,
1791                                 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1792                                 TALLOC_FREE(pathref);
1793                                 SET_STAT_INVALID(smb_fname->st);
1794                                 return NT_STATUS_OK;
1795                         }
1796                         DBG_DEBUG("synthetic_pathref failed: %s\n",
1797                                   nt_errstr(status));
1798                         goto fail;
1799                 }
1800         } else {
1801                 pathref = smb_fname;
1802         }
1803
1804         /* Fall back to a case-insensitive scan of all streams on the file. */
1805         status = vfs_fstreaminfo(pathref->fsp, mem_ctx,
1806                                 &num_streams, &streams);
1807         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1808                 SET_STAT_INVALID(smb_fname->st);
1809                 TALLOC_FREE(pathref);
1810                 return NT_STATUS_OK;
1811         }
1812
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 DEBUG(10, ("vfs_fstreaminfo failed: %s\n", nt_errstr(status)));
1815                 goto fail;
1816         }
1817
1818         for (i=0; i<num_streams; i++) {
1819                 DEBUG(10, ("comparing [%s] and [%s]: ",
1820                            smb_fname->stream_name, streams[i].name));
1821                 if (sname_equal(smb_fname->stream_name, streams[i].name,
1822                                 conn->case_sensitive)) {
1823                         DEBUGADD(10, ("equal\n"));
1824                         break;
1825                 }
1826                 DEBUGADD(10, ("not equal\n"));
1827         }
1828
1829         /* Couldn't find the stream. */
1830         if (i == num_streams) {
1831                 SET_STAT_INVALID(smb_fname->st);
1832                 TALLOC_FREE(pathref);
1833                 TALLOC_FREE(streams);
1834                 return NT_STATUS_OK;
1835         }
1836
1837         DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1838                 smb_fname->stream_name, streams[i].name));
1839
1840
1841         TALLOC_FREE(smb_fname->stream_name);
1842         smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
1843         if (smb_fname->stream_name == NULL) {
1844                 status = NT_STATUS_NO_MEMORY;
1845                 goto fail;
1846         }
1847
1848         SET_STAT_INVALID(smb_fname->st);
1849
1850         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1851                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1852         }
1853         status = NT_STATUS_OK;
1854  fail:
1855         TALLOC_FREE(pathref);
1856         TALLOC_FREE(streams);
1857         return status;
1858 }
1859
1860 /*
1861  * Lightweight function to just get last component
1862  * for rename / enumerate directory calls.
1863  */
1864
1865 char *get_original_lcomp(TALLOC_CTX *ctx,
1866                         connection_struct *conn,
1867                         const char *filename_in,
1868                         uint32_t ucf_flags)
1869 {
1870         struct smb_filename *smb_fname = NULL;
1871         char *last_slash = NULL;
1872         char *orig_lcomp;
1873         char *fname = NULL;
1874         NTTIME twrp = 0;
1875         NTSTATUS status;
1876
1877         if (ucf_flags & UCF_DFS_PATHNAME) {
1878                 status = dfs_redirect(ctx,
1879                                 conn,
1880                                 filename_in,
1881                                 ucf_flags,
1882                                 !conn->sconn->using_smb2,
1883                                 &twrp,
1884                                 &fname);
1885                 if (!NT_STATUS_IS_OK(status)) {
1886                         DBG_DEBUG("dfs_redirect "
1887                                 "failed for name %s with %s\n",
1888                                 filename_in,
1889                                 nt_errstr(status));
1890                         return NULL;
1891                 }
1892                 filename_in = fname;
1893                 ucf_flags &= ~UCF_DFS_PATHNAME;
1894         }
1895
1896         /*
1897          * NB. We don't need to care about
1898          * is_fake_file_path(filename_in) here as these
1899          * code paths don't ever return original_lcomp
1900          * or use it anyway.
1901          */
1902
1903         if (ucf_flags & UCF_GMT_PATHNAME) {
1904                 /*
1905                  * Ensure we don't return a @GMT
1906                  * value as the last component.
1907                  */
1908                 smb_fname = synthetic_smb_fname(ctx,
1909                                         filename_in,
1910                                         NULL,
1911                                         NULL,
1912                                         twrp,
1913                                         0);
1914                 if (smb_fname == NULL) {
1915                         TALLOC_FREE(fname);
1916                         return NULL;
1917                 }
1918                 status = canonicalize_snapshot_path(smb_fname,
1919                                                     ucf_flags,
1920                                                     twrp);
1921                 if (!NT_STATUS_IS_OK(status)) {
1922                         TALLOC_FREE(fname);
1923                         TALLOC_FREE(smb_fname);
1924                         return NULL;
1925                 }
1926                 filename_in = smb_fname->base_name;
1927         }
1928         last_slash = strrchr(filename_in, '/');
1929         if (last_slash != NULL) {
1930                 orig_lcomp = talloc_strdup(ctx, last_slash+1);
1931         } else {
1932                 orig_lcomp = talloc_strdup(ctx, filename_in);
1933         }
1934         /* We're done with any temp names here. */
1935         TALLOC_FREE(smb_fname);
1936         TALLOC_FREE(fname);
1937         if (orig_lcomp == NULL) {
1938                 return NULL;
1939         }
1940         status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
1941         if (!NT_STATUS_IS_OK(status)) {
1942                 TALLOC_FREE(orig_lcomp);
1943                 return NULL;
1944         }
1945         return orig_lcomp;
1946 }
1947
1948 /**
1949  * Go through all the steps to validate a filename.
1950  *
1951  * @param ctx           talloc_ctx to allocate memory with.
1952  * @param conn          connection struct for vfs calls.
1953  * @param smbreq        SMB request if we're using privileges.
1954  * @param name_in       The unconverted name.
1955  * @param ucf_flags     flags to pass through to unix_convert().
1956  * @param twrp          Optional VSS time
1957  * @param p_cont_wcard  If not NULL, will be set to true if the dfs path
1958  *                      resolution detects a wildcard.
1959  * @param _smb_fname    The final converted name will be allocated if the
1960  *                      return is NT_STATUS_OK.
1961  *
1962  * @return NT_STATUS_OK if all operations completed successfully, appropriate
1963  *         error otherwise.
1964  */
1965 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1966                           connection_struct *conn,
1967                           const char *name_in,
1968                           uint32_t ucf_flags,
1969                           NTTIME twrp,
1970                           struct smb_filename **_smb_fname)
1971 {
1972         struct smb_filename *smb_fname = NULL;
1973         NTSTATUS status;
1974
1975         *_smb_fname = NULL;
1976
1977         if (ucf_flags & UCF_DFS_PATHNAME) {
1978                 char *fname = NULL;
1979                 NTTIME dfs_twrp = 0;
1980                 status = dfs_redirect(ctx, conn,
1981                                 name_in,
1982                                 ucf_flags,
1983                                 !conn->sconn->using_smb2,
1984                                 &dfs_twrp,
1985                                 &fname);
1986                 if (!NT_STATUS_IS_OK(status)) {
1987                         DBG_DEBUG("dfs_redirect "
1988                                 "failed for name %s with %s\n",
1989                                 name_in,
1990                                 nt_errstr(status));
1991                         return status;
1992                 }
1993                 name_in = fname;
1994                 ucf_flags &= ~UCF_DFS_PATHNAME;
1995                 if (twrp == 0 && dfs_twrp != 0) {
1996                         twrp = dfs_twrp;
1997                 }
1998         }
1999
2000         if (is_fake_file_path(name_in)) {
2001                 smb_fname = synthetic_smb_fname_split(ctx,
2002                                         name_in,
2003                                         (ucf_flags & UCF_POSIX_PATHNAMES));
2004                 if (smb_fname == NULL) {
2005                         return NT_STATUS_NO_MEMORY;
2006                 }
2007                 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2008                 smb_fname->st.st_ex_btime = (struct timespec){0, SAMBA_UTIME_OMIT};
2009                 smb_fname->st.st_ex_atime = (struct timespec){0, SAMBA_UTIME_OMIT};
2010                 smb_fname->st.st_ex_mtime = (struct timespec){0, SAMBA_UTIME_OMIT};
2011                 smb_fname->st.st_ex_ctime = (struct timespec){0, SAMBA_UTIME_OMIT};
2012
2013                 *_smb_fname = smb_fname;
2014                 return NT_STATUS_OK;
2015         }
2016
2017         status = unix_convert(ctx, conn, name_in, twrp, &smb_fname, ucf_flags);
2018         if (!NT_STATUS_IS_OK(status)) {
2019                 DBG_DEBUG("unix_convert failed "
2020                         "for name %s with %s\n",
2021                         name_in,
2022                         nt_errstr(status));
2023                 return status;
2024         }
2025
2026         if ((ucf_flags & UCF_POSIX_PATHNAMES) &&
2027             VALID_STAT(smb_fname->st) &&
2028             S_ISLNK(smb_fname->st.st_ex_mode))
2029         {
2030                 status = check_veto_path(conn, smb_fname);
2031                 if (!NT_STATUS_IS_OK(status)) {
2032                         TALLOC_FREE(smb_fname);
2033                         return status;
2034                 }
2035         } else {
2036                 status = check_name(conn, smb_fname);
2037         }
2038         if (!NT_STATUS_IS_OK(status)) {
2039                 DBG_NOTICE("check_name failed "
2040                         "for name %s with %s\n",
2041                         smb_fname_str_dbg(smb_fname),
2042                         nt_errstr(status));
2043                 TALLOC_FREE(smb_fname);
2044                 return status;
2045         }
2046
2047         if (!VALID_STAT(smb_fname->st)) {
2048                 DBG_DEBUG("[%s] does not exist, skipping pathref fsp\n",
2049                           smb_fname_str_dbg(smb_fname));
2050                 *_smb_fname = smb_fname;
2051                 return NT_STATUS_OK;
2052         }
2053
2054         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
2055         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2056                 /*
2057                  * We deal with symlinks here as we do in
2058                  * SMB_VFS_CREATE_FILE(): return success for POSIX clients with
2059                  * the notable difference that there will be no fsp in
2060                  * smb_fname->fsp.
2061                  *
2062                  * For Windows (non POSIX) clients fail with
2063                  * NT_STATUS_OBJECT_NAME_NOT_FOUND.
2064                  */
2065                 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH &&
2066                     S_ISLNK(smb_fname->st.st_ex_mode))
2067                 {
2068                         status = NT_STATUS_OK;
2069                 }
2070         }
2071         if (!NT_STATUS_IS_OK(status)) {
2072                 DBG_DEBUG("open_pathref_fsp [%s] failed: %s\n",
2073                           smb_fname_str_dbg(smb_fname),
2074                           nt_errstr(status));
2075                 return status;
2076         }
2077
2078         *_smb_fname = smb_fname;
2079         return status;
2080 }
2081
2082 /*
2083  * Strip a @GMT component from an SMB1-DFS path. Could be anywhere
2084  * in the path.
2085  */
2086
2087 static char *strip_gmt_from_raw_dfs(TALLOC_CTX *ctx,
2088                                     const char *name_in,
2089                                     bool posix_pathnames,
2090                                     NTTIME *_twrp)
2091 {
2092         NTSTATUS status;
2093         struct smb_filename *smb_fname = NULL;
2094         char *name_out = NULL;
2095
2096         smb_fname = synthetic_smb_fname(ctx,
2097                                         name_in,
2098                                         NULL,
2099                                         NULL,
2100                                         0,
2101                                         0);
2102         if (smb_fname == NULL) {
2103                 return NULL;
2104         }
2105         if (!posix_pathnames) {
2106                 /*
2107                  * Raw DFS names are still '\\' separated.
2108                  * canonicalize_snapshot_path() only works
2109                  * on '/' separated paths. Convert.
2110                  */
2111                 string_replace(smb_fname->base_name, '\\', '/');
2112         }
2113         status = canonicalize_snapshot_path(smb_fname,
2114                                             UCF_GMT_PATHNAME,
2115                                             0);
2116         if (!NT_STATUS_IS_OK(status)) {
2117                 TALLOC_FREE(smb_fname);
2118                 return NULL;
2119         }
2120         if (!posix_pathnames) {
2121                 /* Replace as raw DFS names. */
2122                 string_replace(smb_fname->base_name, '/', '\\');
2123         }
2124         name_out = talloc_strdup(ctx, smb_fname->base_name);
2125         *_twrp = smb_fname->twrp;
2126         TALLOC_FREE(smb_fname);
2127         return name_out;
2128 }
2129
2130 /*
2131  * Deal with the SMB1 semantics of sending a pathname with a
2132  * wildcard as the terminal component for a SMB1search or
2133  * trans2 findfirst.
2134  */
2135
2136 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
2137                                            connection_struct *conn,
2138                                            const char *name_in,
2139                                            uint32_t ucf_flags,
2140                                            struct smb_filename **_smb_fname_out,
2141                                            char **_mask_out)
2142 {
2143         NTSTATUS status;
2144         char *p = NULL;
2145         char *mask = NULL;
2146         struct smb_filename *smb_fname = NULL;
2147         bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
2148         NTTIME twrp = 0;
2149         TALLOC_CTX *frame = talloc_stackframe();
2150
2151         *_smb_fname_out = NULL;
2152         *_mask_out = NULL;
2153
2154         DBG_DEBUG("name_in: %s\n", name_in);
2155
2156         if (ucf_flags & UCF_DFS_PATHNAME) {
2157                 /*
2158                  * We've been given a raw DFS pathname.
2159                  * In Windows mode this is separated by '\\'
2160                  * characters.
2161                  *
2162                  * We need to remove the last component
2163                  * which must be a wildcard before passing
2164                  * to dfs_redirect(). But the last component
2165                  * may also be a @GMT- token so we have to
2166                  * remove that first.
2167                  */
2168                 char path_sep = posix_pathnames ? '/' : '\\';
2169                 char *fname = NULL;
2170                 char *name_in_copy = NULL;
2171                 char *last_component = NULL;
2172
2173                 /* Work on a copy of name_in. */
2174                 if (ucf_flags & UCF_GMT_PATHNAME) {
2175                         name_in_copy = strip_gmt_from_raw_dfs(frame,
2176                                                               name_in,
2177                                                               posix_pathnames,
2178                                                               &twrp);
2179                         ucf_flags &= ~UCF_GMT_PATHNAME;
2180                 } else {
2181                         name_in_copy = talloc_strdup(frame, name_in);
2182                 }
2183                 if (name_in_copy == NULL) {
2184                         TALLOC_FREE(frame);
2185                         return NT_STATUS_NO_MEMORY;
2186                 }
2187
2188                 /*
2189                  * Now we know that the last component is the
2190                  * wildcard. Copy it and truncate to remove it.
2191                  */
2192                 p = strrchr_m(name_in_copy, path_sep);
2193                 if (p == NULL) {
2194                         last_component = talloc_strdup(frame, name_in_copy);
2195                         name_in_copy[0] = '\0';
2196                 } else {
2197                         last_component = talloc_strdup(frame, p+1);
2198                         *p = '\0';
2199                 }
2200                 if (last_component == NULL) {
2201                         TALLOC_FREE(frame);
2202                         return NT_STATUS_NO_MEMORY;
2203                 }
2204
2205                 DBG_DEBUG("name_in_copy: %s\n", name_in);
2206
2207                 /*
2208                  * Now we can call dfs_redirect()
2209                  * on the name without wildcard.
2210                  */
2211                 status = dfs_redirect(frame,
2212                                       conn,
2213                                       name_in_copy,
2214                                       ucf_flags,
2215                                       !conn->sconn->using_smb2,
2216                                       NULL,
2217                                       &fname);
2218                 if (!NT_STATUS_IS_OK(status)) {
2219                         DBG_DEBUG("dfs_redirect "
2220                                 "failed for name %s with %s\n",
2221                                 name_in_copy,
2222                                 nt_errstr(status));
2223                         TALLOC_FREE(frame);
2224                         return status;
2225                 }
2226                 /* Add the last component back. */
2227                 if (fname[0] == '\0') {
2228                         name_in = talloc_strdup(frame, last_component);
2229                 } else {
2230                         name_in = talloc_asprintf(frame,
2231                                                   "%s%c%s",
2232                                                   fname,
2233                                                   path_sep,
2234                                                   last_component);
2235                 }
2236                 if (name_in == NULL) {
2237                         TALLOC_FREE(frame);
2238                         return NT_STATUS_NO_MEMORY;
2239                 }
2240                 ucf_flags &= ~UCF_DFS_PATHNAME;
2241
2242                 DBG_DEBUG("After DFS redirect name_in: %s\n", name_in);
2243         }
2244
2245         smb_fname = synthetic_smb_fname(frame,
2246                                         name_in,
2247                                         NULL,
2248                                         NULL,
2249                                         twrp,
2250                                         posix_pathnames ?
2251                                                 SMB_FILENAME_POSIX_PATH : 0);
2252         if (smb_fname == NULL) {
2253                 TALLOC_FREE(frame);
2254                 return NT_STATUS_NO_MEMORY;
2255         }
2256
2257         /* Canonicalize any @GMT- paths. */
2258         status = canonicalize_snapshot_path(smb_fname, ucf_flags, twrp);
2259         if (!NT_STATUS_IS_OK(status)) {
2260                 TALLOC_FREE(frame);
2261                 return status;
2262         }
2263
2264         /* Get the original lcomp. */
2265         mask = get_original_lcomp(frame,
2266                                   conn,
2267                                   name_in,
2268                                   ucf_flags);
2269         if (mask == NULL) {
2270                 TALLOC_FREE(frame);
2271                 return NT_STATUS_NO_MEMORY;
2272         }
2273
2274         if (mask[0] == '\0') {
2275                 /* Windows and OS/2 systems treat search on the root as * */
2276                 TALLOC_FREE(mask);
2277                 mask = talloc_strdup(frame, "*");
2278                 if (mask == NULL) {
2279                         TALLOC_FREE(frame);
2280                         return NT_STATUS_NO_MEMORY;
2281                 }
2282         }
2283
2284         DBG_DEBUG("mask = %s\n", mask);
2285
2286         /*
2287          * Remove the terminal component so
2288          * filename_convert never sees the mask.
2289          */
2290         p = strrchr_m(smb_fname->base_name,'/');
2291         if (p == NULL) {
2292                 /* filename_convert handles a '\0' base_name. */
2293                 smb_fname->base_name[0] = '\0';
2294         } else {
2295                 *p = '\0';
2296         }
2297
2298         DBG_DEBUG("For filename_convert: smb_fname = %s\n",
2299                 smb_fname_str_dbg(smb_fname));
2300
2301         /* Convert the parent directory path. */
2302         status = filename_convert(frame,
2303                                   conn,
2304                                   smb_fname->base_name,
2305                                   ucf_flags,
2306                                   smb_fname->twrp,
2307                                   &smb_fname);
2308
2309         if (NT_STATUS_IS_OK(status)) {
2310                 *_smb_fname_out = talloc_move(ctx, &smb_fname);
2311                 *_mask_out = talloc_move(ctx, &mask);
2312         } else {
2313                 DBG_DEBUG("filename_convert error for %s: %s\n",
2314                         smb_fname_str_dbg(smb_fname),
2315                         nt_errstr(status));
2316         }
2317
2318         TALLOC_FREE(frame);
2319         return status;
2320 }
2321
2322 /*
2323  * Build the full path from a dirfsp and dirfsp relative name
2324  */
2325 struct smb_filename *full_path_from_dirfsp_atname(
2326         TALLOC_CTX *mem_ctx,
2327         const struct files_struct *dirfsp,
2328         const struct smb_filename *atname)
2329 {
2330         struct smb_filename *fname = NULL;
2331         char *path = NULL;
2332
2333         if (dirfsp == dirfsp->conn->cwd_fsp ||
2334             ISDOT(dirfsp->fsp_name->base_name) ||
2335             atname->base_name[0] == '/')
2336         {
2337                 path = talloc_strdup(mem_ctx, atname->base_name);
2338         } else {
2339                 path = talloc_asprintf(mem_ctx, "%s/%s",
2340                                        dirfsp->fsp_name->base_name,
2341                                        atname->base_name);
2342         }
2343         if (path == NULL) {
2344                 return NULL;
2345         }
2346
2347         fname = synthetic_smb_fname(mem_ctx,
2348                                     path,
2349                                     atname->stream_name,
2350                                     &atname->st,
2351                                     atname->twrp,
2352                                     atname->flags);
2353         TALLOC_FREE(path);
2354         if (fname == NULL) {
2355                 return NULL;
2356         }
2357
2358         return fname;
2359 }