Fix bug #Bug 6090 renaming or deleting a "not matching/resolving" symlink is failing.
[samba.git] / source / 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
29 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
30                                   connection_struct *conn,
31                                   const char *orig_path,
32                                   const char *basepath,
33                                   const char *streamname,
34                                   SMB_STRUCT_STAT *pst,
35                                   char **path);
36
37 /****************************************************************************
38  Mangle the 2nd name and check if it is then equal to the first name.
39 ****************************************************************************/
40
41 static bool mangled_equal(const char *name1,
42                         const char *name2,
43                         const struct share_params *p)
44 {
45         char mname[13];
46
47         if (!name_to_8_3(name2, mname, False, p)) {
48                 return False;
49         }
50         return strequal(name1, mname);
51 }
52
53 /****************************************************************************
54  Cope with the differing wildcard and non-wildcard error cases.
55 ****************************************************************************/
56
57 static NTSTATUS determine_path_error(const char *name,
58                         bool allow_wcard_last_component)
59 {
60         const char *p;
61
62         if (!allow_wcard_last_component) {
63                 /* Error code within a pathname. */
64                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
65         }
66
67         /* We're terminating here so we
68          * can be a little slower and get
69          * the error code right. Windows
70          * treats the last part of the pathname
71          * separately I think, so if the last
72          * component is a wildcard then we treat
73          * this ./ as "end of component" */
74
75         p = strchr(name, '/');
76
77         if (!p && (ms_has_wild(name) || ISDOT(name))) {
78                 /* Error code at the end of a pathname. */
79                 return NT_STATUS_OBJECT_NAME_INVALID;
80         } else {
81                 /* Error code within a pathname. */
82                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
83         }
84 }
85
86 /****************************************************************************
87 This routine is called to convert names from the dos namespace to unix
88 namespace. It needs to handle any case conversions, mangling, format
89 changes etc.
90
91 We assume that we have already done a chdir() to the right "root" directory
92 for this service.
93
94 The function will return an NTSTATUS error if some part of the name except for
95 the last part cannot be resolved, else NT_STATUS_OK.
96
97 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
98 get any fatal errors that should immediately terminate the calling
99 SMB processing whilst resolving.
100
101 If the saved_last_component != 0, then the unmodified last component
102 of the pathname is returned there. If saved_last_component == 0 then nothing
103 is returned there.
104
105 If last_component_wcard is true then a MS wildcard was detected and
106 should be allowed in the last component of the path only.
107
108 On exit from unix_convert, if *pst was not null, then the file stat
109 struct will be returned if the file exists and was found, if not this
110 stat struct will be filled with zeros (and this can be detected by checking
111 for nlinks = 0, which can never be true for any file).
112 ****************************************************************************/
113
114 NTSTATUS unix_convert(TALLOC_CTX *ctx,
115                         connection_struct *conn,
116                         const char *orig_path,
117                         bool allow_wcard_last_component,
118                         char **pp_conv_path,
119                         char **pp_saved_last_component,
120                         SMB_STRUCT_STAT *pst)
121 {
122         SMB_STRUCT_STAT st;
123         char *start, *end;
124         char *dirpath = NULL;
125         char *name = NULL;
126         char *stream = NULL;
127         bool component_was_mangled = False;
128         bool name_has_wildcard = False;
129         bool posix_pathnames = false;
130         NTSTATUS result;
131         int ret = -1;
132
133         SET_STAT_INVALID(*pst);
134         *pp_conv_path = NULL;
135         if(pp_saved_last_component) {
136                 *pp_saved_last_component = NULL;
137         }
138
139         if (conn->printer) {
140                 /* we don't ever use the filenames on a printer share as a
141                         filename - so don't convert them */
142                 if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
143                         return NT_STATUS_NO_MEMORY;
144                 }
145                 return NT_STATUS_OK;
146         }
147
148         DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
149
150         /*
151          * Conversion to basic unix format is already done in
152          * check_path_syntax().
153          */
154
155         /*
156          * Names must be relative to the root of the service - any leading /.
157          * and trailing /'s should have been trimmed by check_path_syntax().
158          */
159
160 #ifdef DEVELOPER
161         SMB_ASSERT(*orig_path != '/');
162 #endif
163
164         /*
165          * If we trimmed down to a single '\0' character
166          * then we should use the "." directory to avoid
167          * searching the cache, but not if we are in a
168          * printing share.
169          * As we know this is valid we can return true here.
170          */
171
172         if (!*orig_path) {
173                 if (!(name = talloc_strdup(ctx,"."))) {
174                         return NT_STATUS_NO_MEMORY;
175                 }
176                 if (SMB_VFS_STAT(conn,name,&st) == 0) {
177                         *pst = st;
178                 } else {
179                         return map_nt_error_from_unix(errno);
180                 }
181                 DEBUG(5,("conversion finished \"\" -> %s\n",name));
182                 goto done;
183         }
184
185         if (orig_path[0] == '.' && (orig_path[1] == '/' ||
186                                 orig_path[1] == '\0')) {
187                 /* Start of pathname can't be "." only. */
188                 if (orig_path[1] == '\0' || orig_path[2] == '\0') {
189                         result = NT_STATUS_OBJECT_NAME_INVALID;
190                 } else {
191                         result =determine_path_error(
192                                 &orig_path[2], allow_wcard_last_component);
193                 }
194                 return result;
195         }
196
197         if (!(name = talloc_strdup(ctx, orig_path))) {
198                 DEBUG(0, ("talloc_strdup failed\n"));
199                 return NT_STATUS_NO_MEMORY;
200         }
201
202         /*
203          * Large directory fix normalization. If we're case sensitive, and
204          * the case preserving parameters are set to "no", normalize the case of
205          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
206          * This is in conflict with the current (3.0.20) man page, but is
207          * what people expect from the "large directory howto". I'll update
208          * the man page. Thanks to jht@samba.org for finding this. JRA.
209          */
210
211         if (conn->case_sensitive && !conn->case_preserve &&
212                         !conn->short_case_preserve) {
213                 strnorm(name, lp_defaultcase(SNUM(conn)));
214         }
215
216         /*
217          * Ensure saved_last_component is valid even if file exists.
218          */
219
220         if(pp_saved_last_component) {
221                 end = strrchr_m(name, '/');
222                 if (end) {
223                         *pp_saved_last_component = talloc_strdup(ctx, end + 1);
224                 } else {
225                         *pp_saved_last_component = talloc_strdup(ctx,
226                                                         name);
227                 }
228         }
229
230         posix_pathnames = lp_posix_pathnames();
231
232         if (!posix_pathnames) {
233                 stream = strchr_m(name, ':');
234
235                 if (stream != NULL) {
236                         char *tmp = talloc_strdup(ctx, stream);
237                         if (tmp == NULL) {
238                                 TALLOC_FREE(name);
239                                 return NT_STATUS_NO_MEMORY;
240                         }
241                         *stream = '\0';
242                         stream = tmp;
243                 }
244         }
245
246         start = name;
247
248         /* If we're providing case insentive semantics or
249          * the underlying filesystem is case insensitive,
250          * then a case-normalized hit in the stat-cache is
251          * authoratitive. JRA.
252          */
253
254         if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
255                         stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
256                 *pst = st;
257                 goto done;
258         }
259
260         /*
261          * Make sure "dirpath" is an allocated string, we use this for
262          * building the directories with asprintf and free it.
263          */
264
265         if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
266                 DEBUG(0, ("talloc_strdup failed\n"));
267                 TALLOC_FREE(name);
268                 return NT_STATUS_NO_MEMORY;
269         }
270
271         /*
272          * stat the name - if it exists then we are all done!
273          */
274
275         if (posix_pathnames) {
276                 ret = SMB_VFS_LSTAT(conn,name,&st);
277         } else {
278                 ret = SMB_VFS_STAT(conn,name,&st);
279         }
280
281         if (ret == 0) {
282                 /* Ensure we catch all names with in "/."
283                    this is disallowed under Windows. */
284                 const char *p = strstr(name, "/."); /* mb safe. */
285                 if (p) {
286                         if (p[2] == '/') {
287                                 /* Error code within a pathname. */
288                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
289                                 goto fail;
290                         } else if (p[2] == '\0') {
291                                 /* Error code at the end of a pathname. */
292                                 result = NT_STATUS_OBJECT_NAME_INVALID;
293                                 goto fail;
294                         }
295                 }
296                 stat_cache_add(orig_path, name, conn->case_sensitive);
297                 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
298                 *pst = st;
299                 goto done;
300         }
301
302         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
303                                 name, dirpath, start));
304
305         /*
306          * A special case - if we don't have any mangling chars and are case
307          * sensitive or the underlying filesystem is case insentive then searching
308          * won't help.
309          */
310
311         if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
312                         !mangle_is_mangled(name, conn->params)) {
313                 goto done;
314         }
315
316         /*
317          * is_mangled() was changed to look at an entire pathname, not
318          * just a component. JRA.
319          */
320
321         if (mangle_is_mangled(start, conn->params)) {
322                 component_was_mangled = True;
323         }
324
325         /*
326          * Now we need to recursively match the name against the real
327          * directory structure.
328          */
329
330         /*
331          * Match each part of the path name separately, trying the names
332          * as is first, then trying to scan the directory for matching names.
333          */
334
335         for (; start ; start = (end?end+1:(char *)NULL)) {
336                 /*
337                  * Pinpoint the end of this section of the filename.
338                  */
339                 /* mb safe. '/' can't be in any encoded char. */
340                 end = strchr(start, '/');
341
342                 /*
343                  * Chop the name at this point.
344                  */
345                 if (end) {
346                         *end = 0;
347                 }
348
349                 if (pp_saved_last_component) {
350                         TALLOC_FREE(*pp_saved_last_component);
351                         *pp_saved_last_component = talloc_strdup(ctx,
352                                                         end ? end + 1 : start);
353                         if (!*pp_saved_last_component) {
354                                 DEBUG(0, ("talloc failed\n"));
355                                 return NT_STATUS_NO_MEMORY;
356                         }
357                 }
358
359                 /* The name cannot have a component of "." */
360
361                 if (ISDOT(start)) {
362                         if (!end)  {
363                                 /* Error code at the end of a pathname. */
364                                 result = NT_STATUS_OBJECT_NAME_INVALID;
365                         } else {
366                                 result = determine_path_error(end+1,
367                                                 allow_wcard_last_component);
368                         }
369                         goto fail;
370                 }
371
372                 /* The name cannot have a wildcard if it's not
373                    the last component. */
374
375                 name_has_wildcard = ms_has_wild(start);
376
377                 /* Wildcard not valid anywhere. */
378                 if (name_has_wildcard && !allow_wcard_last_component) {
379                         result = NT_STATUS_OBJECT_NAME_INVALID;
380                         goto fail;
381                 }
382
383                 /* Wildcards never valid within a pathname. */
384                 if (name_has_wildcard && end) {
385                         result = NT_STATUS_OBJECT_NAME_INVALID;
386                         goto fail;
387                 }
388
389                 /*
390                  * Check if the name exists up to this point.
391                  */
392
393                 if (posix_pathnames) {
394                         ret = SMB_VFS_LSTAT(conn,name, &st);
395                 } else {
396                         ret = SMB_VFS_STAT(conn,name, &st);
397                 }
398
399                 if (ret == 0) {
400                         /*
401                          * It exists. it must either be a directory or this must
402                          * be the last part of the path for it to be OK.
403                          */
404                         if (end && !(st.st_mode & S_IFDIR)) {
405                                 /*
406                                  * An intermediate part of the name isn't
407                                  * a directory.
408                                  */
409                                 DEBUG(5,("Not a dir %s\n",start));
410                                 *end = '/';
411                                 /*
412                                  * We need to return the fact that the
413                                  * intermediate name resolution failed. This
414                                  * is used to return an error of ERRbadpath
415                                  * rather than ERRbadfile. Some Windows
416                                  * applications depend on the difference between
417                                  * these two errors.
418                                  */
419                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
420                                 goto fail;
421                         }
422
423                         if (!end) {
424                                 /*
425                                  * We just scanned for, and found the end of
426                                  * the path. We must return the valid stat
427                                  * struct. JRA.
428                                  */
429
430                                 *pst = st;
431                         }
432
433                 } else {
434                         char *found_name = NULL;
435
436                         /* Stat failed - ensure we don't use it. */
437                         SET_STAT_INVALID(st);
438
439                         /*
440                          * Reset errno so we can detect
441                          * directory open errors.
442                          */
443                         errno = 0;
444
445                         /*
446                          * Try to find this part of the path in the directory.
447                          */
448
449                         if (name_has_wildcard ||
450                             (SMB_VFS_GET_REAL_FILENAME(
451                                      conn, dirpath, start,
452                                      talloc_tos(), &found_name) == -1)) {
453                                 char *unmangled;
454
455                                 if (end) {
456                                         /*
457                                          * An intermediate part of the name
458                                          * can't be found.
459                                          */
460                                         DEBUG(5,("Intermediate not found %s\n",
461                                                         start));
462                                         *end = '/';
463
464                                         /*
465                                          * We need to return the fact that the
466                                          * intermediate name resolution failed.
467                                          * This is used to return an error of
468                                          * ERRbadpath rather than ERRbadfile.
469                                          * Some Windows applications depend on
470                                          * the difference between these two
471                                          * errors.
472                                          */
473
474                                         /*
475                                          * ENOENT, ENOTDIR and ELOOP all map
476                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
477                                          * in the filename walk.
478                                          */
479
480                                         if (errno == ENOENT ||
481                                                         errno == ENOTDIR ||
482                                                         errno == ELOOP) {
483                                                 result =
484                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
485                                         }
486                                         else {
487                                                 result =
488                                                 map_nt_error_from_unix(errno);
489                                         }
490                                         goto fail;
491                                 }
492
493                                 /* ENOENT is the only valid error here. */
494                                 if ((errno != 0) && (errno != ENOENT)) {
495                                         /*
496                                          * ENOTDIR and ELOOP both map to
497                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
498                                          * in the filename walk.
499                                          */
500                                         if (errno == ENOTDIR ||
501                                                         errno == ELOOP) {
502                                                 result =
503                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
504                                         }
505                                         else {
506                                                 result =
507                                                 map_nt_error_from_unix(errno);
508                                         }
509                                         goto fail;
510                                 }
511
512                                 /*
513                                  * Just the last part of the name doesn't exist.
514                                  * We need to strupper() or strlower() it as
515                                  * this conversion may be used for file creation
516                                  * purposes. Fix inspired by
517                                  * Thomas Neumann <t.neumann@iku-ag.de>.
518                                  */
519                                 if (!conn->case_preserve ||
520                                     (mangle_is_8_3(start, False,
521                                                    conn->params) &&
522                                                  !conn->short_case_preserve)) {
523                                         strnorm(start,
524                                                 lp_defaultcase(SNUM(conn)));
525                                 }
526
527                                 /*
528                                  * check on the mangled stack to see if we can
529                                  * recover the base of the filename.
530                                  */
531
532                                 if (mangle_is_mangled(start, conn->params)
533                                     && mangle_lookup_name_from_8_3(ctx,
534                                                         start,
535                                                         &unmangled,
536                                                         conn->params)) {
537                                         char *tmp;
538                                         size_t start_ofs = start - name;
539
540                                         if (*dirpath != '\0') {
541                                                 tmp = talloc_asprintf(ctx,
542                                                         "%s/%s", dirpath,
543                                                         unmangled);
544                                                 TALLOC_FREE(unmangled);
545                                         }
546                                         else {
547                                                 tmp = unmangled;
548                                         }
549                                         if (tmp == NULL) {
550                                                 DEBUG(0, ("talloc failed\n"));
551                                                 return NT_STATUS_NO_MEMORY;
552                                         }
553                                         TALLOC_FREE(name);
554                                         name = tmp;
555                                         start = name + start_ofs;
556                                         end = start + strlen(start);
557                                 }
558
559                                 DEBUG(5,("New file %s\n",start));
560                                 goto done;
561                         }
562
563
564                         /*
565                          * Restore the rest of the string. If the string was
566                          * mangled the size may have changed.
567                          */
568                         if (end) {
569                                 char *tmp;
570                                 size_t start_ofs = start - name;
571
572                                 if (*dirpath != '\0') {
573                                         tmp = talloc_asprintf(ctx,
574                                                 "%s/%s/%s", dirpath,
575                                                 found_name, end+1);
576                                 }
577                                 else {
578                                         tmp = talloc_asprintf(ctx,
579                                                 "%s/%s", found_name,
580                                                 end+1);
581                                 }
582                                 if (tmp == NULL) {
583                                         DEBUG(0, ("talloc_asprintf failed\n"));
584                                         return NT_STATUS_NO_MEMORY;
585                                 }
586                                 TALLOC_FREE(name);
587                                 name = tmp;
588                                 start = name + start_ofs;
589                                 end = start + strlen(found_name);
590                                 *end = '\0';
591                         } else {
592                                 char *tmp;
593                                 size_t start_ofs = start - name;
594
595                                 if (*dirpath != '\0') {
596                                         tmp = talloc_asprintf(ctx,
597                                                 "%s/%s", dirpath,
598                                                 found_name);
599                                 } else {
600                                         tmp = talloc_strdup(ctx,
601                                                 found_name);
602                                 }
603                                 if (tmp == NULL) {
604                                         DEBUG(0, ("talloc failed\n"));
605                                         return NT_STATUS_NO_MEMORY;
606                                 }
607                                 TALLOC_FREE(name);
608                                 name = tmp;
609                                 start = name + start_ofs;
610
611                                 /*
612                                  * We just scanned for, and found the end of
613                                  * the path. We must return a valid stat struct
614                                  * if it exists. JRA.
615                                  */
616
617                                 if (posix_pathnames) {
618                                         ret = SMB_VFS_LSTAT(conn,name, &st);
619                                 } else {
620                                         ret = SMB_VFS_STAT(conn,name, &st);
621                                 }
622
623                                 if (ret == 0) {
624                                         *pst = st;
625                                 } else {
626                                         SET_STAT_INVALID(st);
627                                 }
628                         }
629
630                         TALLOC_FREE(found_name);
631                 } /* end else */
632
633 #ifdef DEVELOPER
634                 /*
635                  * This sucks!
636                  * We should never provide different behaviors
637                  * depending on DEVELOPER!!!
638                  */
639                 if (VALID_STAT(st)) {
640                         bool delete_pending;
641                         get_file_infos(vfs_file_id_from_sbuf(conn, &st),
642                                        &delete_pending, NULL);
643                         if (delete_pending) {
644                                 result = NT_STATUS_DELETE_PENDING;
645                                 goto fail;
646                         }
647                 }
648 #endif
649
650                 /*
651                  * Add to the dirpath that we have resolved so far.
652                  */
653
654                 if (*dirpath != '\0') {
655                         char *tmp = talloc_asprintf(ctx,
656                                         "%s/%s", dirpath, start);
657                         if (!tmp) {
658                                 DEBUG(0, ("talloc_asprintf failed\n"));
659                                 return NT_STATUS_NO_MEMORY;
660                         }
661                         TALLOC_FREE(dirpath);
662                         dirpath = tmp;
663                 }
664                 else {
665                         TALLOC_FREE(dirpath);
666                         if (!(dirpath = talloc_strdup(ctx,start))) {
667                                 DEBUG(0, ("talloc_strdup failed\n"));
668                                 return NT_STATUS_NO_MEMORY;
669                         }
670                 }
671
672                 /*
673                  * Don't cache a name with mangled or wildcard components
674                  * as this can change the size.
675                  */
676
677                 if(!component_was_mangled && !name_has_wildcard) {
678                         stat_cache_add(orig_path, dirpath,
679                                         conn->case_sensitive);
680                 }
681
682                 /*
683                  * Restore the / that we wiped out earlier.
684                  */
685                 if (end) {
686                         *end = '/';
687                 }
688         }
689
690         /*
691          * Don't cache a name with mangled or wildcard components
692          * as this can change the size.
693          */
694
695         if(!component_was_mangled && !name_has_wildcard) {
696                 stat_cache_add(orig_path, name, conn->case_sensitive);
697         }
698
699         /*
700          * The name has been resolved.
701          */
702
703         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
704
705  done:
706         if (stream != NULL) {
707                 char *tmp = NULL;
708
709                 result = build_stream_path(ctx, conn, orig_path, name, stream,
710                                            pst, &tmp);
711                 if (!NT_STATUS_IS_OK(result)) {
712                         goto fail;
713                 }
714
715                 DEBUG(10, ("build_stream_path returned %s\n", tmp));
716
717                 TALLOC_FREE(name);
718                 name = tmp;
719         }
720         *pp_conv_path = name;
721         TALLOC_FREE(dirpath);
722         return NT_STATUS_OK;
723  fail:
724         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
725         if (*dirpath != '\0') {
726                 *pp_conv_path = talloc_asprintf(ctx,
727                                 "%s/%s", dirpath, start);
728         } else {
729                 *pp_conv_path = talloc_strdup(ctx, start);
730         }
731         if (!*pp_conv_path) {
732                 DEBUG(0, ("talloc_asprintf failed\n"));
733                 return NT_STATUS_NO_MEMORY;
734         }
735         TALLOC_FREE(name);
736         TALLOC_FREE(dirpath);
737         return result;
738 }
739
740 /****************************************************************************
741  Check a filename - possibly calling check_reduced_name.
742  This is called by every routine before it allows an operation on a filename.
743  It does any final confirmation necessary to ensure that the filename is
744  a valid one for the user to access.
745 ****************************************************************************/
746
747 NTSTATUS check_name(connection_struct *conn, const char *name)
748 {
749         if (IS_VETO_PATH(conn, name))  {
750                 /* Is it not dot or dot dot. */
751                 if (!((name[0] == '.') && (!name[1] ||
752                                         (name[1] == '.' && !name[2])))) {
753                         DEBUG(5,("check_name: file path name %s vetoed\n",
754                                                 name));
755                         return map_nt_error_from_unix(ENOENT);
756                 }
757         }
758
759         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
760                 NTSTATUS status = check_reduced_name(conn,name);
761                 if (!NT_STATUS_IS_OK(status)) {
762                         DEBUG(5,("check_name: name %s failed with %s\n",name,
763                                                 nt_errstr(status)));
764                         return status;
765                 }
766         }
767
768         return NT_STATUS_OK;
769 }
770
771 /****************************************************************************
772  Check if two filenames are equal.
773  This needs to be careful about whether we are case sensitive.
774 ****************************************************************************/
775
776 static bool fname_equal(const char *name1, const char *name2,
777                 bool case_sensitive)
778 {
779         /* Normal filename handling */
780         if (case_sensitive) {
781                 return(strcmp(name1,name2) == 0);
782         }
783
784         return(strequal(name1,name2));
785 }
786
787 /****************************************************************************
788  Scan a directory to find a filename, matching without case sensitivity.
789  If the name looks like a mangled name then try via the mangling functions
790 ****************************************************************************/
791
792 int get_real_filename(connection_struct *conn, const char *path,
793                       const char *name, TALLOC_CTX *mem_ctx,
794                       char **found_name)
795 {
796         struct smb_Dir *cur_dir;
797         const char *dname;
798         bool mangled;
799         char *unmangled_name = NULL;
800         long curpos;
801
802         mangled = mangle_is_mangled(name, conn->params);
803
804         /* handle null paths */
805         if ((path == NULL) || (*path == 0)) {
806                 path = ".";
807         }
808
809         /* If we have a case-sensitive filesystem, it doesn't do us any
810          * good to search for a name. If a case variation of the name was
811          * there, then the original stat(2) would have found it.
812          */
813         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
814                 errno = ENOENT;
815                 return -1;
816         }
817
818         /*
819          * The incoming name can be mangled, and if we de-mangle it
820          * here it will not compare correctly against the filename (name2)
821          * read from the directory and then mangled by the name_to_8_3()
822          * call. We need to mangle both names or neither.
823          * (JRA).
824          *
825          * Fix for bug found by Dina Fine. If in case sensitive mode then
826          * the mangle cache is no good (3 letter extension could be wrong
827          * case - so don't demangle in this case - leave as mangled and
828          * allow the mangling of the directory entry read (which is done
829          * case insensitively) to match instead. This will lead to more
830          * false positive matches but we fail completely without it. JRA.
831          */
832
833         if (mangled && !conn->case_sensitive) {
834                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
835                                                        &unmangled_name,
836                                                        conn->params);
837                 if (!mangled) {
838                         /* Name is now unmangled. */
839                         name = unmangled_name;
840                 }
841         }
842
843         /* open the directory */
844         if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
845                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
846                 TALLOC_FREE(unmangled_name);
847                 return -1;
848         }
849
850         /* now scan for matching names */
851         curpos = 0;
852         while ((dname = ReadDirName(cur_dir, &curpos))) {
853
854                 /* Is it dot or dot dot. */
855                 if (ISDOT(dname) || ISDOTDOT(dname)) {
856                         continue;
857                 }
858
859                 /*
860                  * At this point dname is the unmangled name.
861                  * name is either mangled or not, depending on the state
862                  * of the "mangled" variable. JRA.
863                  */
864
865                 /*
866                  * Check mangled name against mangled name, or unmangled name
867                  * against unmangled name.
868                  */
869
870                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
871                         fname_equal(name, dname, conn->case_sensitive)) {
872                         /* we've found the file, change it's name and return */
873                         *found_name = talloc_strdup(mem_ctx, dname);
874                         TALLOC_FREE(unmangled_name);
875                         TALLOC_FREE(cur_dir);
876                         if (!*found_name) {
877                                 errno = ENOMEM;
878                                 return -1;
879                         }
880                         return 0;
881                 }
882         }
883
884         TALLOC_FREE(unmangled_name);
885         TALLOC_FREE(cur_dir);
886         errno = ENOENT;
887         return -1;
888 }
889
890 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
891                                   connection_struct *conn,
892                                   const char *orig_path,
893                                   const char *basepath,
894                                   const char *streamname,
895                                   SMB_STRUCT_STAT *pst,
896                                   char **path)
897 {
898         SMB_STRUCT_STAT st;
899         char *result = NULL;
900         NTSTATUS status;
901         unsigned int i, num_streams;
902         struct stream_struct *streams = NULL;
903
904         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
905         if (result == NULL) {
906                 return NT_STATUS_NO_MEMORY;
907         }
908
909         if (SMB_VFS_STAT(conn, result, &st) == 0) {
910                 *pst = st;
911                 *path = result;
912                 return NT_STATUS_OK;
913         }
914
915         if (errno != ENOENT) {
916                 status = map_nt_error_from_unix(errno);
917                 DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
918                 goto fail;
919         }
920
921         status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
922                                     &num_streams, &streams);
923
924         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
925                 SET_STAT_INVALID(*pst);
926                 *path = result;
927                 return NT_STATUS_OK;
928         }
929
930         if (!NT_STATUS_IS_OK(status)) {
931                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
932                 goto fail;
933         }
934
935         for (i=0; i<num_streams; i++) {
936                 DEBUG(10, ("comparing [%s] and [%s]: ",
937                            streamname, streams[i].name));
938                 if (fname_equal(streamname, streams[i].name,
939                                 conn->case_sensitive)) {
940                         DEBUGADD(10, ("equal\n"));
941                         break;
942                 }
943                 DEBUGADD(10, ("not equal\n"));
944         }
945
946         if (i == num_streams) {
947                 SET_STAT_INVALID(*pst);
948                 *path = result;
949                 TALLOC_FREE(streams);
950                 return NT_STATUS_OK;
951         }
952
953         TALLOC_FREE(result);
954
955         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
956         if (result == NULL) {
957                 status = NT_STATUS_NO_MEMORY;
958                 goto fail;
959         }
960
961         SET_STAT_INVALID(*pst);
962
963         if (SMB_VFS_STAT(conn, result, pst) == 0) {
964                 stat_cache_add(orig_path, result, conn->case_sensitive);
965         }
966
967         *path = result;
968         TALLOC_FREE(streams);
969         return NT_STATUS_OK;
970
971  fail:
972         TALLOC_FREE(result);
973         TALLOC_FREE(streams);
974         return status;
975 }