Optimization suggested by Metze. Without this patch,
[metze/samba/wip.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 "fake_file.h"
29
30 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
31                                   connection_struct *conn,
32                                   const char *orig_path,
33                                   struct smb_filename *smb_fname);
34
35 /****************************************************************************
36  Mangle the 2nd name and check if it is then equal to the first name.
37 ****************************************************************************/
38
39 static bool mangled_equal(const char *name1,
40                         const char *name2,
41                         const struct share_params *p)
42 {
43         char mname[13];
44
45         if (!name_to_8_3(name2, mname, False, p)) {
46                 return False;
47         }
48         return strequal(name1, mname);
49 }
50
51 /****************************************************************************
52  Cope with the differing wildcard and non-wildcard error cases.
53 ****************************************************************************/
54
55 static NTSTATUS determine_path_error(const char *name,
56                         bool allow_wcard_last_component)
57 {
58         const char *p;
59
60         if (!allow_wcard_last_component) {
61                 /* Error code within a pathname. */
62                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
63         }
64
65         /* We're terminating here so we
66          * can be a little slower and get
67          * the error code right. Windows
68          * treats the last part of the pathname
69          * separately I think, so if the last
70          * component is a wildcard then we treat
71          * this ./ as "end of component" */
72
73         p = strchr(name, '/');
74
75         if (!p && (ms_has_wild(name) || ISDOT(name))) {
76                 /* Error code at the end of a pathname. */
77                 return NT_STATUS_OBJECT_NAME_INVALID;
78         } else {
79                 /* Error code within a pathname. */
80                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
81         }
82 }
83
84 static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
85 {
86         /* Ensure we catch all names with in "/."
87            this is disallowed under Windows and
88            in POSIX they've already been removed. */
89         const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
90         if (p) {
91                 if (p[2] == '/') {
92                         /* Error code within a pathname. */
93                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
94                 } else if (p[2] == '\0') {
95                         /* Error code at the end of a pathname. */
96                         return NT_STATUS_OBJECT_NAME_INVALID;
97                 }
98         }
99         return NT_STATUS_OK;
100 }
101
102 /****************************************************************************
103 This routine is called to convert names from the dos namespace to unix
104 namespace. It needs to handle any case conversions, mangling, format changes,
105 streams etc.
106
107 We assume that we have already done a chdir() to the right "root" directory
108 for this service.
109
110 The function will return an NTSTATUS error if some part of the name except for
111 the last part cannot be resolved, else NT_STATUS_OK.
112
113 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
114 didn't get any fatal errors that should immediately terminate the calling SMB
115 processing whilst resolving.
116
117 If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
118 of the pathname is set in smb_filename->original_lcomp.
119
120 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
121 and should be allowed in the last component of the path only.
122
123 If the orig_path was a stream, smb_filename->base_name will point to the base
124 filename, and smb_filename->stream_name will point to the stream name.  If
125 orig_path was not a stream, then smb_filename->stream_name will be NULL.
126
127 On exit from unix_convert, the smb_filename->st stat struct will be populated
128 if the file exists and was found, if not this stat struct will be filled with
129 zeros (and this can be detected by checking for nlinks = 0, which can never be
130 true for any file).
131 ****************************************************************************/
132
133 NTSTATUS unix_convert(TALLOC_CTX *ctx,
134                       connection_struct *conn,
135                       const char *orig_path,
136                       struct smb_filename **smb_fname_out,
137                       uint32_t ucf_flags)
138 {
139         struct smb_filename *smb_fname = NULL;
140         char *start, *end;
141         char *dirpath = NULL;
142         char *stream = NULL;
143         bool component_was_mangled = False;
144         bool name_has_wildcard = False;
145         bool posix_pathnames = false;
146         bool allow_wcard_last_component =
147             (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
148         bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
149         NTSTATUS status;
150         int ret = -1;
151
152         *smb_fname_out = NULL;
153
154         smb_fname = talloc_zero(ctx, struct smb_filename);
155         if (smb_fname == NULL) {
156                 return NT_STATUS_NO_MEMORY;
157         }
158
159         if (conn->printer) {
160                 /* we don't ever use the filenames on a printer share as a
161                         filename - so don't convert them */
162                 if (!(smb_fname->base_name = talloc_strdup(smb_fname,
163                                                            orig_path))) {
164                         status = NT_STATUS_NO_MEMORY;
165                         goto err;
166                 }
167                 goto done;
168         }
169
170         DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
171
172         /*
173          * Conversion to basic unix format is already done in
174          * check_path_syntax().
175          */
176
177         /*
178          * Names must be relative to the root of the service - any leading /.
179          * and trailing /'s should have been trimmed by check_path_syntax().
180          */
181
182 #ifdef DEVELOPER
183         SMB_ASSERT(*orig_path != '/');
184 #endif
185
186         /*
187          * If we trimmed down to a single '\0' character
188          * then we should use the "." directory to avoid
189          * searching the cache, but not if we are in a
190          * printing share.
191          * As we know this is valid we can return true here.
192          */
193
194         if (!*orig_path) {
195                 if (!(smb_fname->base_name = talloc_strdup(smb_fname, "."))) {
196                         status = NT_STATUS_NO_MEMORY;
197                         goto err;
198                 }
199                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
200                         status = map_nt_error_from_unix(errno);
201                         goto err;
202                 }
203                 DEBUG(5, ("conversion finished \"\" -> %s\n",
204                           smb_fname->base_name));
205                 goto done;
206         }
207
208         if (orig_path[0] == '.' && (orig_path[1] == '/' ||
209                                 orig_path[1] == '\0')) {
210                 /* Start of pathname can't be "." only. */
211                 if (orig_path[1] == '\0' || orig_path[2] == '\0') {
212                         status = NT_STATUS_OBJECT_NAME_INVALID;
213                 } else {
214                         status =determine_path_error(&orig_path[2],
215                             allow_wcard_last_component);
216                 }
217                 goto err;
218         }
219
220         /* Start with the full orig_path as given by the caller. */
221         if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) {
222                 DEBUG(0, ("talloc_strdup failed\n"));
223                 status = NT_STATUS_NO_MEMORY;
224                 goto err;
225         }
226
227         /*
228          * Large directory fix normalization. If we're case sensitive, and
229          * the case preserving parameters are set to "no", normalize the case of
230          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
231          * This is in conflict with the current (3.0.20) man page, but is
232          * what people expect from the "large directory howto". I'll update
233          * the man page. Thanks to jht@samba.org for finding this. JRA.
234          */
235
236         if (conn->case_sensitive && !conn->case_preserve &&
237                         !conn->short_case_preserve) {
238                 strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn)));
239         }
240
241         /*
242          * Ensure saved_last_component is valid even if file exists.
243          */
244
245         if(save_last_component) {
246                 end = strrchr_m(smb_fname->base_name, '/');
247                 if (end) {
248                         smb_fname->original_lcomp = talloc_strdup(smb_fname,
249                                                                   end + 1);
250                 } else {
251                         smb_fname->original_lcomp =
252                             talloc_strdup(smb_fname, smb_fname->base_name);
253                 }
254                 if (smb_fname->original_lcomp == NULL) {
255                         status = NT_STATUS_NO_MEMORY;
256                         goto err;
257                 }
258         }
259
260         posix_pathnames = (lp_posix_pathnames() ||
261                                 (ucf_flags & UCF_POSIX_PATHNAMES));
262
263         /*
264          * Strip off the stream, and add it back when we're done with the
265          * base_name.
266          */
267         if (!posix_pathnames) {
268                 stream = strchr_m(smb_fname->base_name, ':');
269
270                 if (stream != NULL) {
271                         char *tmp = talloc_strdup(smb_fname, stream);
272                         if (tmp == NULL) {
273                                 status = NT_STATUS_NO_MEMORY;
274                                 goto err;
275                         }
276                         /*
277                          * Since this is actually pointing into
278                          * smb_fname->base_name this truncates base_name.
279                          */
280                         *stream = '\0';
281                         stream = tmp;
282                 }
283         }
284
285         start = smb_fname->base_name;
286
287         /*
288          * If we're providing case insentive semantics or
289          * the underlying filesystem is case insensitive,
290          * then a case-normalized hit in the stat-cache is
291          * authoratitive. JRA.
292          *
293          * Note: We're only checking base_name.  The stream_name will be
294          * added and verified in build_stream_path().
295          */
296
297         if((!conn->case_sensitive || !(conn->fs_capabilities &
298                                        FILE_CASE_SENSITIVE_SEARCH)) &&
299             stat_cache_lookup(conn, &smb_fname->base_name, &dirpath, &start,
300                               &smb_fname->st)) {
301                 goto done;
302         }
303
304         /*
305          * Make sure "dirpath" is an allocated string, we use this for
306          * building the directories with asprintf and free it.
307          */
308
309         if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
310                 DEBUG(0, ("talloc_strdup failed\n"));
311                 status = NT_STATUS_NO_MEMORY;
312                 goto err;
313         }
314
315         /*
316          * If we have a wildcard we must walk the path to
317          * find where the error is, even if case sensitive
318          * is true.
319          */
320
321         name_has_wildcard = ms_has_wild(smb_fname->base_name);
322         if (name_has_wildcard && !allow_wcard_last_component) {
323                 /* Wildcard not valid anywhere. */
324                 status = NT_STATUS_OBJECT_NAME_INVALID;
325                 goto fail;
326         }
327
328         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
329                  smb_fname->base_name, dirpath, start));
330
331         if (!name_has_wildcard) {
332                 /*
333                  * stat the name - if it exists then we can add the stream back (if
334                  * there was one) and be done!
335                  */
336
337                 if (posix_pathnames) {
338                         ret = SMB_VFS_LSTAT(conn, smb_fname);
339                 } else {
340                         ret = SMB_VFS_STAT(conn, smb_fname);
341                 }
342
343                 if (ret == 0) {
344                         status = check_for_dot_component(smb_fname);
345                         if (!NT_STATUS_IS_OK(status)) {
346                                 goto fail;
347                         }
348                         /* Add the path (not including the stream) to the cache. */
349                         stat_cache_add(orig_path, smb_fname->base_name,
350                                        conn->case_sensitive);
351                         DEBUG(5,("conversion of base_name finished %s -> %s\n",
352                                  orig_path, smb_fname->base_name));
353                         goto done;
354                 }
355
356                 /*
357                  * A special case - if we don't have any wildcards or mangling chars and are case
358                  * sensitive or the underlying filesystem is case insentive then searching
359                  * won't help.
360                  */
361
362                 if ((conn->case_sensitive || !(conn->fs_capabilities &
363                                         FILE_CASE_SENSITIVE_SEARCH)) &&
364                                 !mangle_is_mangled(smb_fname->base_name, conn->params)) {
365
366                         status = check_for_dot_component(smb_fname);
367                         if (!NT_STATUS_IS_OK(status)) {
368                                 goto fail;
369                         }
370
371                         /*
372                          * The stat failed. Could be ok as it could be
373                          * a new file.
374                          */
375
376                         if (errno == ENOTDIR || errno == ELOOP) {
377                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
378                                 goto fail;
379                         } else if (errno == ENOENT) {
380                                 /*
381                                  * Was it a missing last component ?
382                                  * or a missing intermediate component ?
383                                  */
384                                 struct smb_filename parent_fname;
385                                 const char *last_component = NULL;
386
387                                 ZERO_STRUCT(parent_fname);
388                                 if (!parent_dirname(ctx, smb_fname->base_name,
389                                                         &parent_fname.base_name,
390                                                         &last_component)) {
391                                         status = NT_STATUS_NO_MEMORY;
392                                         goto fail;
393                                 }
394                                 if (posix_pathnames) {
395                                         ret = SMB_VFS_LSTAT(conn, &parent_fname);
396                                 } else {
397                                         ret = SMB_VFS_STAT(conn, &parent_fname);
398                                 }
399                                 if (ret == -1) {
400                                         if (errno == ENOTDIR ||
401                                                         errno == ENOENT ||
402                                                         errno == ELOOP) {
403                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
404                                                 goto fail;
405                                         }
406                                 } else if (ret == 0) {
407                                         /*
408                                          * stat() or lstat() of the parent dir
409                                          * succeeded. So start the walk
410                                          * at this point.
411                                          */
412                                         status = check_for_dot_component(&parent_fname);
413                                         if (!NT_STATUS_IS_OK(status)) {
414                                                 goto fail;
415                                         }
416
417                                         /*
418                                          * If there was no parent component in
419                                          * smb_fname->base_name then
420                                          * don't do this optimization.
421                                          */
422                                         if (smb_fname->base_name != last_component) {
423                                                 /*
424                                                  * Safe to use CONST_DISCARD
425                                                  * here as last_component points
426                                                  * into our smb_fname->base_name.
427                                                  */
428                                                 start = CONST_DISCARD(char *,
429                                                         last_component);
430
431                                                 DEBUG(5,("unix_convert optimize1: name "
432                                                         "= %s, dirpath = %s, "
433                                                         "start = %s\n",
434                                                         smb_fname->base_name,
435                                                         dirpath,
436                                                         start));
437                                         }
438                                 }
439
440                                 /*
441                                  * Missing last component is ok - new file.
442                                  * Also deal with permission denied elsewhere.
443                                  * Just drop out to done.
444                                  */
445                                 goto done;
446                         }
447                 }
448         } else {
449                 /*
450                  * We have a wildcard in the pathname.
451                  *
452                  * Optimization for common case where the wildcard
453                  * is in the last component and the client already
454                  * sent the correct case.
455                  */
456                 struct smb_filename parent_fname;
457                 const char *last_component = NULL;
458
459                 ZERO_STRUCT(parent_fname);
460                 if (!parent_dirname(ctx, smb_fname->base_name,
461                                         &parent_fname.base_name,
462                                         &last_component)) {
463                         status = NT_STATUS_NO_MEMORY;
464                         goto fail;
465                 }
466                 /*
467                  * If there was no parent component in
468                  * smb_fname->base_name then
469                  * don't do this optimization.
470                  */
471                 if ((smb_fname->base_name != last_component) &&
472                                 !ms_has_wild(parent_fname.base_name)) {
473                         /*
474                          * Wildcard isn't in the parent, i.e.
475                          * it must be in the last component.
476                          */
477                         if (posix_pathnames) {
478                                 ret = SMB_VFS_LSTAT(conn, &parent_fname);
479                         } else {
480                                 ret = SMB_VFS_STAT(conn, &parent_fname);
481                         }
482                         if (ret == 0) {
483                                 status = check_for_dot_component(&parent_fname);
484                                 if (!NT_STATUS_IS_OK(status)) {
485                                         goto fail;
486                                 }
487
488                                 /*
489                                  * Safe to use CONST_DISCARD
490                                  * here as last_component points
491                                  * into our smb_fname->base_name.
492                                  */
493                                 start = CONST_DISCARD(char *,last_component);
494
495                                 DEBUG(5,("unix_convert optimize2: name "
496                                         "= %s, dirpath = %s, "
497                                         "start = %s\n",
498                                         smb_fname->base_name,
499                                         dirpath,
500                                         start));
501                         }
502                 }
503         }
504
505         /*
506          * is_mangled() was changed to look at an entire pathname, not
507          * just a component. JRA.
508          */
509
510         if (mangle_is_mangled(start, conn->params)) {
511                 component_was_mangled = True;
512         }
513
514         /*
515          * Now we need to recursively match the name against the real
516          * directory structure.
517          */
518
519         /*
520          * Match each part of the path name separately, trying the names
521          * as is first, then trying to scan the directory for matching names.
522          */
523
524         for (; start ; start = (end?end+1:(char *)NULL)) {
525                 /*
526                  * Pinpoint the end of this section of the filename.
527                  */
528                 /* mb safe. '/' can't be in any encoded char. */
529                 end = strchr(start, '/');
530
531                 /*
532                  * Chop the name at this point.
533                  */
534                 if (end) {
535                         *end = 0;
536                 }
537
538                 if (save_last_component) {
539                         TALLOC_FREE(smb_fname->original_lcomp);
540                         smb_fname->original_lcomp = talloc_strdup(smb_fname,
541                                                         end ? end + 1 : start);
542                         if (!smb_fname->original_lcomp) {
543                                 DEBUG(0, ("talloc failed\n"));
544                                 status = NT_STATUS_NO_MEMORY;
545                                 goto err;
546                         }
547                 }
548
549                 /* The name cannot have a component of "." */
550
551                 if (ISDOT(start)) {
552                         if (!end)  {
553                                 /* Error code at the end of a pathname. */
554                                 status = NT_STATUS_OBJECT_NAME_INVALID;
555                         } else {
556                                 status = determine_path_error(end+1,
557                                                 allow_wcard_last_component);
558                         }
559                         goto fail;
560                 }
561
562                 /* The name cannot have a wildcard if it's not
563                    the last component. */
564
565                 name_has_wildcard = ms_has_wild(start);
566
567                 /* Wildcards never valid within a pathname. */
568                 if (name_has_wildcard && end) {
569                         status = NT_STATUS_OBJECT_NAME_INVALID;
570                         goto fail;
571                 }
572
573                 /* Skip the stat call if it's a wildcard end. */
574                 if (name_has_wildcard) {
575                         DEBUG(5,("Wildcard %s\n",start));
576                         goto done;
577                 }
578
579                 /*
580                  * Check if the name exists up to this point.
581                  */
582
583                 if (posix_pathnames) {
584                         ret = SMB_VFS_LSTAT(conn, smb_fname);
585                 } else {
586                         ret = SMB_VFS_STAT(conn, smb_fname);
587                 }
588
589                 if (ret == 0) {
590                         /*
591                          * It exists. it must either be a directory or this must
592                          * be the last part of the path for it to be OK.
593                          */
594                         if (end && !S_ISDIR(smb_fname->st.st_ex_mode)) {
595                                 /*
596                                  * An intermediate part of the name isn't
597                                  * a directory.
598                                  */
599                                 DEBUG(5,("Not a dir %s\n",start));
600                                 *end = '/';
601                                 /*
602                                  * We need to return the fact that the
603                                  * intermediate name resolution failed. This
604                                  * is used to return an error of ERRbadpath
605                                  * rather than ERRbadfile. Some Windows
606                                  * applications depend on the difference between
607                                  * these two errors.
608                                  */
609                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
610                                 goto fail;
611                         }
612
613                 } else {
614                         char *found_name = NULL;
615
616                         /* Stat failed - ensure we don't use it. */
617                         SET_STAT_INVALID(smb_fname->st);
618
619                         /*
620                          * Reset errno so we can detect
621                          * directory open errors.
622                          */
623                         errno = 0;
624
625                         /*
626                          * Try to find this part of the path in the directory.
627                          */
628
629                         if (name_has_wildcard ||
630                             (get_real_filename(conn, dirpath, start,
631                                                talloc_tos(),
632                                                &found_name) == -1)) {
633                                 char *unmangled;
634
635                                 if (end) {
636                                         /*
637                                          * An intermediate part of the name
638                                          * can't be found.
639                                          */
640                                         DEBUG(5,("Intermediate not found %s\n",
641                                                         start));
642                                         *end = '/';
643
644                                         /*
645                                          * We need to return the fact that the
646                                          * intermediate name resolution failed.
647                                          * This is used to return an error of
648                                          * ERRbadpath rather than ERRbadfile.
649                                          * Some Windows applications depend on
650                                          * the difference between these two
651                                          * errors.
652                                          */
653
654                                         /*
655                                          * ENOENT, ENOTDIR and ELOOP all map
656                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
657                                          * in the filename walk.
658                                          */
659
660                                         if (errno == ENOENT ||
661                                                         errno == ENOTDIR ||
662                                                         errno == ELOOP) {
663                                                 status =
664                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
665                                         }
666                                         else {
667                                                 status =
668                                                 map_nt_error_from_unix(errno);
669                                         }
670                                         goto fail;
671                                 }
672
673                                 /*
674                                  * ENOENT/EACCESS are the only valid errors
675                                  * here. EACCESS needs handling here for
676                                  * "dropboxes", i.e. directories where users
677                                  * can only put stuff with permission -wx.
678                                  */
679                                 if ((errno != 0) && (errno != ENOENT)
680                                     && (errno != EACCES)) {
681                                         /*
682                                          * ENOTDIR and ELOOP both map to
683                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
684                                          * in the filename walk.
685                                          */
686                                         if (errno == ENOTDIR ||
687                                                         errno == ELOOP) {
688                                                 status =
689                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
690                                         } else {
691                                                 status =
692                                                 map_nt_error_from_unix(errno);
693                                         }
694                                         goto fail;
695                                 }
696
697                                 /*
698                                  * Just the last part of the name doesn't exist.
699                                  * We need to strupper() or strlower() it as
700                                  * this conversion may be used for file creation
701                                  * purposes. Fix inspired by
702                                  * Thomas Neumann <t.neumann@iku-ag.de>.
703                                  */
704                                 if (!conn->case_preserve ||
705                                     (mangle_is_8_3(start, False,
706                                                    conn->params) &&
707                                                  !conn->short_case_preserve)) {
708                                         strnorm(start,
709                                                 lp_defaultcase(SNUM(conn)));
710                                 }
711
712                                 /*
713                                  * check on the mangled stack to see if we can
714                                  * recover the base of the filename.
715                                  */
716
717                                 if (mangle_is_mangled(start, conn->params)
718                                     && mangle_lookup_name_from_8_3(ctx,
719                                                         start,
720                                                         &unmangled,
721                                                         conn->params)) {
722                                         char *tmp;
723                                         size_t start_ofs =
724                                             start - smb_fname->base_name;
725
726                                         if (*dirpath != '\0') {
727                                                 tmp = talloc_asprintf(
728                                                         smb_fname, "%s/%s",
729                                                         dirpath, unmangled);
730                                                 TALLOC_FREE(unmangled);
731                                         }
732                                         else {
733                                                 tmp = unmangled;
734                                         }
735                                         if (tmp == NULL) {
736                                                 DEBUG(0, ("talloc failed\n"));
737                                                 status = NT_STATUS_NO_MEMORY;
738                                                 goto err;
739                                         }
740                                         TALLOC_FREE(smb_fname->base_name);
741                                         smb_fname->base_name = tmp;
742                                         start =
743                                             smb_fname->base_name + start_ofs;
744                                         end = start + strlen(start);
745                                 }
746
747                                 DEBUG(5,("New file %s\n",start));
748                                 goto done;
749                         }
750
751
752                         /*
753                          * Restore the rest of the string. If the string was
754                          * mangled the size may have changed.
755                          */
756                         if (end) {
757                                 char *tmp;
758                                 size_t start_ofs =
759                                     start - smb_fname->base_name;
760
761                                 if (*dirpath != '\0') {
762                                         tmp = talloc_asprintf(smb_fname,
763                                                 "%s/%s/%s", dirpath,
764                                                 found_name, end+1);
765                                 }
766                                 else {
767                                         tmp = talloc_asprintf(smb_fname,
768                                                 "%s/%s", found_name,
769                                                 end+1);
770                                 }
771                                 if (tmp == NULL) {
772                                         DEBUG(0, ("talloc_asprintf failed\n"));
773                                         status = NT_STATUS_NO_MEMORY;
774                                         goto err;
775                                 }
776                                 TALLOC_FREE(smb_fname->base_name);
777                                 smb_fname->base_name = tmp;
778                                 start = smb_fname->base_name + start_ofs;
779                                 end = start + strlen(found_name);
780                                 *end = '\0';
781                         } else {
782                                 char *tmp;
783                                 size_t start_ofs =
784                                     start - smb_fname->base_name;
785
786                                 if (*dirpath != '\0') {
787                                         tmp = talloc_asprintf(smb_fname,
788                                                 "%s/%s", dirpath,
789                                                 found_name);
790                                 } else {
791                                         tmp = talloc_strdup(smb_fname,
792                                                 found_name);
793                                 }
794                                 if (tmp == NULL) {
795                                         DEBUG(0, ("talloc failed\n"));
796                                         status = NT_STATUS_NO_MEMORY;
797                                         goto err;
798                                 }
799                                 TALLOC_FREE(smb_fname->base_name);
800                                 smb_fname->base_name = tmp;
801                                 start = smb_fname->base_name + start_ofs;
802
803                                 /*
804                                  * We just scanned for, and found the end of
805                                  * the path. We must return a valid stat struct
806                                  * if it exists. JRA.
807                                  */
808
809                                 if (posix_pathnames) {
810                                         ret = SMB_VFS_LSTAT(conn, smb_fname);
811                                 } else {
812                                         ret = SMB_VFS_STAT(conn, smb_fname);
813                                 }
814
815                                 if (ret != 0) {
816                                         SET_STAT_INVALID(smb_fname->st);
817                                 }
818                         }
819
820                         TALLOC_FREE(found_name);
821                 } /* end else */
822
823 #ifdef DEVELOPER
824                 /*
825                  * This sucks!
826                  * We should never provide different behaviors
827                  * depending on DEVELOPER!!!
828                  */
829                 if (VALID_STAT(smb_fname->st)) {
830                         bool delete_pending;
831                         get_file_infos(vfs_file_id_from_sbuf(conn,
832                                                              &smb_fname->st),
833                                        &delete_pending, NULL);
834                         if (delete_pending) {
835                                 status = NT_STATUS_DELETE_PENDING;
836                                 goto fail;
837                         }
838                 }
839 #endif
840
841                 /*
842                  * Add to the dirpath that we have resolved so far.
843                  */
844
845                 if (*dirpath != '\0') {
846                         char *tmp = talloc_asprintf(ctx,
847                                         "%s/%s", dirpath, start);
848                         if (!tmp) {
849                                 DEBUG(0, ("talloc_asprintf failed\n"));
850                                 status = NT_STATUS_NO_MEMORY;
851                                 goto err;
852                         }
853                         TALLOC_FREE(dirpath);
854                         dirpath = tmp;
855                 }
856                 else {
857                         TALLOC_FREE(dirpath);
858                         if (!(dirpath = talloc_strdup(ctx,start))) {
859                                 DEBUG(0, ("talloc_strdup failed\n"));
860                                 status = NT_STATUS_NO_MEMORY;
861                                 goto err;
862                         }
863                 }
864
865                 /*
866                  * Cache the dirpath thus far. Don't cache a name with mangled
867                  * or wildcard components as this can change the size.
868                  */
869                 if(!component_was_mangled && !name_has_wildcard) {
870                         stat_cache_add(orig_path, dirpath,
871                                         conn->case_sensitive);
872                 }
873
874                 /*
875                  * Restore the / that we wiped out earlier.
876                  */
877                 if (end) {
878                         *end = '/';
879                 }
880         }
881
882         /*
883          * Cache the full path. Don't cache a name with mangled or wildcard
884          * components as this can change the size.
885          */
886
887         if(!component_was_mangled && !name_has_wildcard) {
888                 stat_cache_add(orig_path, smb_fname->base_name,
889                                conn->case_sensitive);
890         }
891
892         /*
893          * The name has been resolved.
894          */
895
896         DEBUG(5,("conversion finished %s -> %s\n", orig_path,
897                  smb_fname->base_name));
898
899  done:
900         /* Add back the stream if one was stripped off originally. */
901         if (stream != NULL) {
902                 smb_fname->stream_name = stream;
903
904                 /* Check path now that the base_name has been converted. */
905                 status = build_stream_path(ctx, conn, orig_path, smb_fname);
906                 if (!NT_STATUS_IS_OK(status)) {
907                         goto fail;
908                 }
909         }
910         TALLOC_FREE(dirpath);
911         *smb_fname_out = smb_fname;
912         return NT_STATUS_OK;
913  fail:
914         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
915         if (*dirpath != '\0') {
916                 smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
917                                                        dirpath, start);
918         } else {
919                 smb_fname->base_name = talloc_strdup(smb_fname, start);
920         }
921         if (!smb_fname->base_name) {
922                 DEBUG(0, ("talloc_asprintf failed\n"));
923                 status = NT_STATUS_NO_MEMORY;
924                 goto err;
925         }
926
927         *smb_fname_out = smb_fname;
928         TALLOC_FREE(dirpath);
929         return status;
930  err:
931         TALLOC_FREE(smb_fname);
932         return status;
933 }
934
935 /****************************************************************************
936  Check a filename - possibly calling check_reduced_name.
937  This is called by every routine before it allows an operation on a filename.
938  It does any final confirmation necessary to ensure that the filename is
939  a valid one for the user to access.
940 ****************************************************************************/
941
942 NTSTATUS check_name(connection_struct *conn, const char *name)
943 {
944         if (IS_VETO_PATH(conn, name))  {
945                 /* Is it not dot or dot dot. */
946                 if (!((name[0] == '.') && (!name[1] ||
947                                         (name[1] == '.' && !name[2])))) {
948                         DEBUG(5,("check_name: file path name %s vetoed\n",
949                                                 name));
950                         return map_nt_error_from_unix(ENOENT);
951                 }
952         }
953
954         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
955                 NTSTATUS status = check_reduced_name(conn,name);
956                 if (!NT_STATUS_IS_OK(status)) {
957                         DEBUG(5,("check_name: name %s failed with %s\n",name,
958                                                 nt_errstr(status)));
959                         return status;
960                 }
961         }
962
963         return NT_STATUS_OK;
964 }
965
966 /****************************************************************************
967  Check if two filenames are equal.
968  This needs to be careful about whether we are case sensitive.
969 ****************************************************************************/
970
971 static bool fname_equal(const char *name1, const char *name2,
972                 bool case_sensitive)
973 {
974         /* Normal filename handling */
975         if (case_sensitive) {
976                 return(strcmp(name1,name2) == 0);
977         }
978
979         return(strequal(name1,name2));
980 }
981
982 /****************************************************************************
983  Scan a directory to find a filename, matching without case sensitivity.
984  If the name looks like a mangled name then try via the mangling functions
985 ****************************************************************************/
986
987 static int get_real_filename_full_scan(connection_struct *conn,
988                                        const char *path, const char *name,
989                                        bool mangled,
990                                        TALLOC_CTX *mem_ctx, char **found_name)
991 {
992         struct smb_Dir *cur_dir;
993         const char *dname = NULL;
994         char *talloced = NULL;
995         char *unmangled_name = NULL;
996         long curpos;
997
998         /* handle null paths */
999         if ((path == NULL) || (*path == 0)) {
1000                 path = ".";
1001         }
1002
1003         /* If we have a case-sensitive filesystem, it doesn't do us any
1004          * good to search for a name. If a case variation of the name was
1005          * there, then the original stat(2) would have found it.
1006          */
1007         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
1008                 errno = ENOENT;
1009                 return -1;
1010         }
1011
1012         /*
1013          * The incoming name can be mangled, and if we de-mangle it
1014          * here it will not compare correctly against the filename (name2)
1015          * read from the directory and then mangled by the name_to_8_3()
1016          * call. We need to mangle both names or neither.
1017          * (JRA).
1018          *
1019          * Fix for bug found by Dina Fine. If in case sensitive mode then
1020          * the mangle cache is no good (3 letter extension could be wrong
1021          * case - so don't demangle in this case - leave as mangled and
1022          * allow the mangling of the directory entry read (which is done
1023          * case insensitively) to match instead. This will lead to more
1024          * false positive matches but we fail completely without it. JRA.
1025          */
1026
1027         if (mangled && !conn->case_sensitive) {
1028                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
1029                                                        &unmangled_name,
1030                                                        conn->params);
1031                 if (!mangled) {
1032                         /* Name is now unmangled. */
1033                         name = unmangled_name;
1034                 }
1035         }
1036
1037         /* open the directory */
1038         if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
1039                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
1040                 TALLOC_FREE(unmangled_name);
1041                 return -1;
1042         }
1043
1044         /* now scan for matching names */
1045         curpos = 0;
1046         while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
1047
1048                 /* Is it dot or dot dot. */
1049                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1050                         TALLOC_FREE(talloced);
1051                         continue;
1052                 }
1053
1054                 /*
1055                  * At this point dname is the unmangled name.
1056                  * name is either mangled or not, depending on the state
1057                  * of the "mangled" variable. JRA.
1058                  */
1059
1060                 /*
1061                  * Check mangled name against mangled name, or unmangled name
1062                  * against unmangled name.
1063                  */
1064
1065                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
1066                         fname_equal(name, dname, conn->case_sensitive)) {
1067                         /* we've found the file, change it's name and return */
1068                         *found_name = talloc_strdup(mem_ctx, dname);
1069                         TALLOC_FREE(unmangled_name);
1070                         TALLOC_FREE(cur_dir);
1071                         if (!*found_name) {
1072                                 errno = ENOMEM;
1073                                 TALLOC_FREE(talloced);
1074                                 return -1;
1075                         }
1076                         TALLOC_FREE(talloced);
1077                         return 0;
1078                 }
1079                 TALLOC_FREE(talloced);
1080         }
1081
1082         TALLOC_FREE(unmangled_name);
1083         TALLOC_FREE(cur_dir);
1084         errno = ENOENT;
1085         return -1;
1086 }
1087
1088 /****************************************************************************
1089  Wrapper around the vfs get_real_filename and the full directory scan
1090  fallback.
1091 ****************************************************************************/
1092
1093 int get_real_filename(connection_struct *conn, const char *path,
1094                       const char *name, TALLOC_CTX *mem_ctx,
1095                       char **found_name)
1096 {
1097         int ret;
1098         bool mangled;
1099
1100         mangled = mangle_is_mangled(name, conn->params);
1101
1102         if (mangled) {
1103                 return get_real_filename_full_scan(conn, path, name, mangled,
1104                                                    mem_ctx, found_name);
1105         }
1106
1107         /* Try the vfs first to take advantage of case-insensitive stat. */
1108         ret = SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name);
1109
1110         /*
1111          * If the case-insensitive stat was successful, or returned an error
1112          * other than EOPNOTSUPP then there is no need to fall back on the
1113          * full directory scan.
1114          */
1115         if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
1116                 return ret;
1117         }
1118
1119         return get_real_filename_full_scan(conn, path, name, mangled, mem_ctx,
1120                                            found_name);
1121 }
1122
1123 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1124                                   connection_struct *conn,
1125                                   const char *orig_path,
1126                                   struct smb_filename *smb_fname)
1127 {
1128         NTSTATUS status;
1129         unsigned int i, num_streams;
1130         struct stream_struct *streams = NULL;
1131
1132         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1133                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1134                 return NT_STATUS_OK;
1135         }
1136
1137         if (errno != ENOENT) {
1138                 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1139                 status = map_nt_error_from_unix(errno);
1140                 goto fail;
1141         }
1142
1143         /* Fall back to a case-insensitive scan of all streams on the file. */
1144         status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, mem_ctx,
1145                                     &num_streams, &streams);
1146
1147         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1148                 SET_STAT_INVALID(smb_fname->st);
1149                 return NT_STATUS_OK;
1150         }
1151
1152         if (!NT_STATUS_IS_OK(status)) {
1153                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
1154                 goto fail;
1155         }
1156
1157         for (i=0; i<num_streams; i++) {
1158                 DEBUG(10, ("comparing [%s] and [%s]: ",
1159                            smb_fname->stream_name, streams[i].name));
1160                 if (fname_equal(smb_fname->stream_name, streams[i].name,
1161                                 conn->case_sensitive)) {
1162                         DEBUGADD(10, ("equal\n"));
1163                         break;
1164                 }
1165                 DEBUGADD(10, ("not equal\n"));
1166         }
1167
1168         /* Couldn't find the stream. */
1169         if (i == num_streams) {
1170                 SET_STAT_INVALID(smb_fname->st);
1171                 TALLOC_FREE(streams);
1172                 return NT_STATUS_OK;
1173         }
1174
1175         DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1176                 smb_fname->stream_name, streams[i].name));
1177
1178
1179         TALLOC_FREE(smb_fname->stream_name);
1180         smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
1181         if (smb_fname->stream_name == NULL) {
1182                 status = NT_STATUS_NO_MEMORY;
1183                 goto fail;
1184         }
1185
1186         SET_STAT_INVALID(smb_fname->st);
1187
1188         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1189                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1190         }
1191         status = NT_STATUS_OK;
1192  fail:
1193         TALLOC_FREE(streams);
1194         return status;
1195 }
1196
1197 /**
1198  * Go through all the steps to validate a filename.
1199  *
1200  * @param ctx           talloc_ctx to allocate memory with.
1201  * @param conn          connection struct for vfs calls.
1202  * @param dfs_path      Whether this path requires dfs resolution.
1203  * @param name_in       The unconverted name.
1204  * @param ucf_flags     flags to pass through to unix_convert().
1205  *                      UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
1206  *                      p_cont_wcard != NULL and is true and
1207  *                      UCF_COND_ALLOW_WCARD_LCOMP.
1208  * @param p_cont_wcard  If not NULL, will be set to true if the dfs path
1209  *                      resolution detects a wildcard.
1210  * @param pp_smb_fname  The final converted name will be allocated if the
1211  *                      return is NT_STATUS_OK.
1212  *
1213  * @return NT_STATUS_OK if all operations completed succesfully, appropriate
1214  *         error otherwise.
1215  */
1216 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1217                                 connection_struct *conn,
1218                                 bool dfs_path,
1219                                 const char *name_in,
1220                                 uint32_t ucf_flags,
1221                                 bool *ppath_contains_wcard,
1222                                 struct smb_filename **pp_smb_fname)
1223 {
1224         NTSTATUS status;
1225         bool allow_wcards = (ucf_flags & (UCF_COND_ALLOW_WCARD_LCOMP|UCF_ALWAYS_ALLOW_WCARD_LCOMP));
1226         char *fname = NULL;
1227
1228         *pp_smb_fname = NULL;
1229
1230         status = resolve_dfspath_wcard(ctx, conn,
1231                                 dfs_path,
1232                                 name_in,
1233                                 allow_wcards,
1234                                 &fname,
1235                                 ppath_contains_wcard);
1236         if (!NT_STATUS_IS_OK(status)) {
1237                 DEBUG(10,("filename_convert: resolve_dfspath failed "
1238                         "for name %s with %s\n",
1239                         name_in,
1240                         nt_errstr(status) ));
1241                 return status;
1242         }
1243
1244         if (is_fake_file_path(name_in)) {
1245                 SMB_STRUCT_STAT st;
1246                 ZERO_STRUCT(st);
1247                 st.st_ex_nlink = 1;
1248                 status = create_synthetic_smb_fname_split(ctx,
1249                                                           name_in,
1250                                                           &st,
1251                                                           pp_smb_fname);
1252                 return status;
1253         }
1254
1255         /*
1256          * If the caller conditionally allows wildcard lookups, only add the
1257          * always allow if the path actually does contain a wildcard.
1258          */
1259         if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
1260             ppath_contains_wcard != NULL && *ppath_contains_wcard) {
1261                 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
1262         }
1263
1264         status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
1265         if (!NT_STATUS_IS_OK(status)) {
1266                 DEBUG(10,("filename_convert: unix_convert failed "
1267                         "for name %s with %s\n",
1268                         fname,
1269                         nt_errstr(status) ));
1270                 return status;
1271         }
1272
1273         status = check_name(conn, (*pp_smb_fname)->base_name);
1274         if (!NT_STATUS_IS_OK(status)) {
1275                 DEBUG(3,("filename_convert: check_name failed "
1276                         "for name %s with %s\n",
1277                         smb_fname_str_dbg(*pp_smb_fname),
1278                         nt_errstr(status) ));
1279                 TALLOC_FREE(*pp_smb_fname);
1280                 return status;
1281         }
1282
1283         return status;
1284 }