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