16d0f340102672766807d071f04c9d44029a6987
[gd/samba-autobuild/.git] / source3 / smbd / filename.c
1 /*
2    Unix SMB/CIFS implementation.
3    filename handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1999-2007
6    Copyright (C) Ying Chen 2000
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  * New hash table stat cache code added by Ying Chen.
25  */
26
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "fake_file.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32
33 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
34 {
35         uint32_t ucf_flags = 0;
36
37         if (req != NULL) {
38                 if (req->posix_pathnames) {
39                         ucf_flags |= UCF_POSIX_PATHNAMES;
40                 }
41                 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
42                         ucf_flags |= UCF_DFS_PATHNAME;
43                 }
44                 if (req->flags2 & FLAGS2_REPARSE_PATH) {
45                         ucf_flags |= UCF_GMT_PATHNAME;
46                 }
47         }
48
49         return ucf_flags;
50 }
51
52 uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
53 {
54         uint32_t ucf_flags = 0;
55
56         ucf_flags |= ucf_flags_from_smb_request(req);
57
58         switch (create_disposition) {
59         case FILE_OPEN:
60         case FILE_OVERWRITE:
61                 break;
62         case FILE_SUPERSEDE:
63         case FILE_CREATE:
64         case FILE_OPEN_IF:
65         case FILE_OVERWRITE_IF:
66                 ucf_flags |= UCF_PREP_CREATEFILE;
67                 break;
68         }
69
70         return ucf_flags;
71 }
72
73 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
74                                   connection_struct *conn,
75                                   struct smb_filename *smb_fname);
76
77 /****************************************************************************
78  Mangle the 2nd name and check if it is then equal to the first name.
79 ****************************************************************************/
80
81 static bool mangled_equal(const char *name1,
82                         const char *name2,
83                         const struct share_params *p)
84 {
85         char mname[13];
86
87         if (!name_to_8_3(name2, mname, False, p)) {
88                 return False;
89         }
90         return strequal(name1, mname);
91 }
92
93 /****************************************************************************
94  Cope with the differing wildcard and non-wildcard error cases.
95 ****************************************************************************/
96
97 static NTSTATUS determine_path_error(const char *name,
98                         bool allow_wcard_last_component,
99                         bool posix_pathnames)
100 {
101         const char *p;
102         bool name_has_wild = false;
103
104         if (!allow_wcard_last_component) {
105                 /* Error code within a pathname. */
106                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
107         }
108
109         /* We're terminating here so we
110          * can be a little slower and get
111          * the error code right. Windows
112          * treats the last part of the pathname
113          * separately I think, so if the last
114          * component is a wildcard then we treat
115          * this ./ as "end of component" */
116
117         p = strchr(name, '/');
118
119         if (!posix_pathnames) {
120                 name_has_wild = ms_has_wild(name);
121         }
122
123         if (!p && (name_has_wild || ISDOT(name))) {
124                 /* Error code at the end of a pathname. */
125                 return NT_STATUS_OBJECT_NAME_INVALID;
126         } else {
127                 /* Error code within a pathname. */
128                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
129         }
130 }
131
132 static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
133 {
134         /* Ensure we catch all names with in "/."
135            this is disallowed under Windows and
136            in POSIX they've already been removed. */
137         const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
138         if (p) {
139                 if (p[2] == '/') {
140                         /* Error code within a pathname. */
141                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
142                 } else if (p[2] == '\0') {
143                         /* Error code at the end of a pathname. */
144                         return NT_STATUS_OBJECT_NAME_INVALID;
145                 }
146         }
147         return NT_STATUS_OK;
148 }
149
150 /****************************************************************************
151  Optimization for common case where the missing part
152  is in the last component and the client already
153  sent the correct case.
154  Returns NT_STATUS_OK to mean continue the tree walk
155  (possibly with modified start pointer).
156  Any other NT_STATUS_XXX error means terminate the path
157  lookup here.
158 ****************************************************************************/
159
160 static NTSTATUS check_parent_exists(TALLOC_CTX *ctx,
161                                 connection_struct *conn,
162                                 bool posix_pathnames,
163                                 const struct smb_filename *smb_fname,
164                                 char **pp_dirpath,
165                                 char **pp_start)
166 {
167         struct smb_filename parent_fname = {0};
168         const char *last_component = NULL;
169         NTSTATUS status;
170         int ret;
171
172         if (!parent_dirname(ctx, smb_fname->base_name,
173                                 &parent_fname.base_name,
174                                 &last_component)) {
175                 return NT_STATUS_NO_MEMORY;
176         }
177
178         if (!posix_pathnames) {
179                 if (ms_has_wild(parent_fname.base_name)) {
180                         goto no_optimization_out;
181                 }
182         }
183
184         /*
185          * If there was no parent component in
186          * smb_fname->base_name then don't do this
187          * optimization.
188          */
189         if (smb_fname->base_name == last_component) {
190                 goto no_optimization_out;
191         }
192
193         if (posix_pathnames) {
194                 ret = SMB_VFS_LSTAT(conn, &parent_fname);
195         } else {
196                 ret = SMB_VFS_STAT(conn, &parent_fname);
197         }
198
199         /* If the parent stat failed, just continue
200            with the normal tree walk. */
201
202         if (ret == -1) {
203                 goto no_optimization_out;
204         }
205
206         status = check_for_dot_component(&parent_fname);
207         if (!NT_STATUS_IS_OK(status)) {
208                 return status;
209         }
210
211         /* Parent exists - set "start" to be the
212          * last component to shorten the tree walk. */
213
214         /*
215          * Safe to use discard_const_p
216          * here as last_component points
217          * into our smb_fname->base_name.
218          */
219         *pp_start = discard_const_p(char, last_component);
220
221         /* Update dirpath. */
222         TALLOC_FREE(*pp_dirpath);
223         *pp_dirpath = talloc_strdup(ctx, parent_fname.base_name);
224         if (!*pp_dirpath) {
225                 return NT_STATUS_NO_MEMORY;
226         }
227
228         DEBUG(5,("check_parent_exists: name "
229                 "= %s, dirpath = %s, "
230                 "start = %s\n",
231                 smb_fname->base_name,
232                 *pp_dirpath,
233                 *pp_start));
234
235         return NT_STATUS_OK;
236
237   no_optimization_out:
238
239         /*
240          * We must still return an *pp_dirpath
241          * initialized to ".", and a *pp_start
242          * pointing at smb_fname->base_name.
243          */
244
245         TALLOC_FREE(parent_fname.base_name);
246
247         *pp_dirpath = talloc_strdup(ctx, ".");
248         if (*pp_dirpath == NULL) {
249                 return NT_STATUS_NO_MEMORY;
250         }
251         /*
252          * Safe to use discard_const_p
253          * here as by convention smb_fname->base_name
254          * is allocated off ctx.
255          */
256         *pp_start = discard_const_p(char, smb_fname->base_name);
257         return NT_STATUS_OK;
258 }
259
260 /*
261  * Re-order a known good @GMT-token path.
262  */
263
264 static NTSTATUS rearrange_snapshot_path(struct smb_filename *smb_fname,
265                                 char *startp,
266                                 char *endp)
267 {
268         size_t endlen = 0;
269         size_t gmt_len = endp - startp;
270         char gmt_store[gmt_len + 1];
271         char *parent = NULL;
272         const char *last_component = NULL;
273         char *newstr;
274         bool ret;
275
276         DBG_DEBUG("|%s| -> ", smb_fname->base_name);
277
278         /* Save off the @GMT-token. */
279         memcpy(gmt_store, startp, gmt_len);
280         gmt_store[gmt_len] = '\0';
281
282         if (*endp == '/') {
283                 /* Remove any trailing '/' */
284                 endp++;
285         }
286
287         if (*endp == '\0') {
288                 /*
289                  * @GMT-token was at end of path.
290                  * Remove any preceeding '/'
291                  */
292                 if (startp > smb_fname->base_name && startp[-1] == '/') {
293                         startp--;
294                 }
295         }
296
297         /* Remove @GMT-token from the path. */
298         endlen = strlen(endp);
299         memmove(startp, endp, endlen + 1);
300
301         /* Split the remaining path into components. */
302         ret = parent_dirname(smb_fname,
303                                 smb_fname->base_name,
304                                 &parent,
305                                 &last_component);
306         if (ret == false) {
307                 /* Must terminate debug with \n */
308                 DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
309                 return NT_STATUS_NO_MEMORY;
310         }
311
312         if (ISDOT(parent)) {
313                 if (last_component[0] == '\0') {
314                         newstr = talloc_strdup(smb_fname,
315                                         gmt_store);
316                 } else {
317                         newstr = talloc_asprintf(smb_fname,
318                                         "%s/%s",
319                                         gmt_store,
320                                         last_component);
321                 }
322         } else {
323                 newstr = talloc_asprintf(smb_fname,
324                                         "%s/%s/%s",
325                                         gmt_store,
326                                         parent,
327                                         last_component);
328         }
329
330         TALLOC_FREE(parent);
331         TALLOC_FREE(smb_fname->base_name);
332         smb_fname->base_name = newstr;
333
334         DBG_DEBUG("|%s|\n", newstr);
335
336         return NT_STATUS_OK;
337 }
338
339 /*
340  * Canonicalize any incoming pathname potentially containining
341  * a @GMT-token into a path that looks like:
342  *
343  * @GMT-YYYY-MM-DD-HH-MM-SS/path/name/components/last_component
344  *
345  * Leaves single path @GMT-token -component alone:
346  *
347  * @GMT-YYYY-MM-DD-HH-MM-SS -> @GMT-YYYY-MM-DD-HH-MM-SS
348  *
349  * Eventually when struct smb_filename is updated and the VFS
350  * ABI is changed this will remove the @GMT-YYYY-MM-DD-HH-MM-SS
351  * and store in the struct smb_filename as a struct timeval field
352  * instead.
353  */
354
355 static NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname)
356 {
357         char *startp = strchr_m(smb_fname->base_name, '@');
358         char *endp = NULL;
359         struct tm tm;
360
361         if (startp == NULL) {
362                 /* No @ */
363                 return NT_STATUS_OK;
364         }
365
366         startp = strstr_m(startp, "@GMT-");
367         if (startp == NULL) {
368                 /* No @ */
369                 return NT_STATUS_OK;
370         }
371
372         if ((startp > smb_fname->base_name) && (startp[-1] != '/')) {
373                 /* the GMT-token does not start a path-component */
374                 return NT_STATUS_OK;
375         }
376
377         endp = strptime(startp, GMT_FORMAT, &tm);
378         if (endp == NULL) {
379                 /* Not a valid timestring. */
380                 return NT_STATUS_OK;
381         }
382
383         if ( endp[0] == '\0') {
384                 return rearrange_snapshot_path(smb_fname,
385                                         startp,
386                                         endp);
387         }
388
389         if (endp[0] != '/') {
390                 /*
391                  * It is not a complete path component, i.e. the path
392                  * component continues after the gmt-token.
393                  */
394                 return NT_STATUS_OK;
395         }
396
397         return rearrange_snapshot_path(smb_fname,
398                                 startp,
399                                 endp);
400 }
401
402 /****************************************************************************
403 This routine is called to convert names from the dos namespace to unix
404 namespace. It needs to handle any case conversions, mangling, format changes,
405 streams etc.
406
407 We assume that we have already done a chdir() to the right "root" directory
408 for this service.
409
410 The function will return an NTSTATUS error if some part of the name except for
411 the last part cannot be resolved, else NT_STATUS_OK.
412
413 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
414 didn't get any fatal errors that should immediately terminate the calling SMB
415 processing whilst resolving.
416
417 If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
418 of the pathname is set in smb_filename->original_lcomp.
419
420 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
421 and should be allowed in the last component of the path only.
422
423 If the orig_path was a stream, smb_filename->base_name will point to the base
424 filename, and smb_filename->stream_name will point to the stream name.  If
425 orig_path was not a stream, then smb_filename->stream_name will be NULL.
426
427 On exit from unix_convert, the smb_filename->st stat struct will be populated
428 if the file exists and was found, if not this stat struct will be filled with
429 zeros (and this can be detected by checking for nlinks = 0, which can never be
430 true for any file).
431 ****************************************************************************/
432
433 NTSTATUS unix_convert(TALLOC_CTX *ctx,
434                       connection_struct *conn,
435                       const char *orig_path,
436                       struct smb_filename **smb_fname_out,
437                       uint32_t ucf_flags)
438 {
439         struct smb_filename *smb_fname = NULL;
440
441         /*
442          * This looks strange. But we need "start" initialized to "" here but
443          * it can't be a const char *, so 'char *start = "";' does not work.
444          */
445         char cnull = '\0';
446         char *start = &cnull;
447
448         char *end;
449         char *dirpath = NULL;
450         char *stream = NULL;
451         bool component_was_mangled = False;
452         bool name_has_wildcard = False;
453         bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
454         bool allow_wcard_last_component =
455             (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
456         bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
457         bool snapshot_path = (ucf_flags & UCF_GMT_PATHNAME);
458         NTSTATUS status;
459         int ret = -1;
460
461         *smb_fname_out = NULL;
462
463         smb_fname = talloc_zero(ctx, struct smb_filename);
464         if (smb_fname == NULL) {
465                 return NT_STATUS_NO_MEMORY;
466         }
467
468         if (conn->printer) {
469                 /* we don't ever use the filenames on a printer share as a
470                         filename - so don't convert them */
471                 if (!(smb_fname->base_name = talloc_strdup(smb_fname,
472                                                            orig_path))) {
473                         status = NT_STATUS_NO_MEMORY;
474                         goto err;
475                 }
476                 goto done;
477         }
478
479         smb_fname->flags = posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0;
480
481         DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
482
483         /*
484          * Conversion to basic unix format is already done in
485          * check_path_syntax().
486          */
487
488         /*
489          * Names must be relative to the root of the service - any leading /.
490          * and trailing /'s should have been trimmed by check_path_syntax().
491          */
492
493 #ifdef DEVELOPER
494         SMB_ASSERT(*orig_path != '/');
495 #endif
496
497         /*
498          * If we trimmed down to a single '\0' character
499          * then we should use the "." directory to avoid
500          * searching the cache, but not if we are in a
501          * printing share.
502          * As we know this is valid we can return true here.
503          */
504
505         if (!*orig_path) {
506                 if (!(smb_fname->base_name = talloc_strdup(smb_fname, "."))) {
507                         status = NT_STATUS_NO_MEMORY;
508                         goto err;
509                 }
510                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
511                         status = map_nt_error_from_unix(errno);
512                         goto err;
513                 }
514                 DEBUG(5, ("conversion finished \"\" -> %s\n",
515                           smb_fname->base_name));
516                 goto done;
517         }
518
519         if (orig_path[0] == '.' && (orig_path[1] == '/' ||
520                                 orig_path[1] == '\0')) {
521                 /* Start of pathname can't be "." only. */
522                 if (orig_path[1] == '\0' || orig_path[2] == '\0') {
523                         status = NT_STATUS_OBJECT_NAME_INVALID;
524                 } else {
525                         status =determine_path_error(&orig_path[2],
526                             allow_wcard_last_component,
527                             posix_pathnames);
528                 }
529                 goto err;
530         }
531
532         /* Start with the full orig_path as given by the caller. */
533         if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) {
534                 DEBUG(0, ("talloc_strdup failed\n"));
535                 status = NT_STATUS_NO_MEMORY;
536                 goto err;
537         }
538
539         /* Canonicalize any @GMT- paths. */
540         if (snapshot_path) {
541                 status = canonicalize_snapshot_path(smb_fname);
542                 if (!NT_STATUS_IS_OK(status)) {
543                         goto err;
544                 }
545         }
546
547         /*
548          * Large directory fix normalization. If we're case sensitive, and
549          * the case preserving parameters are set to "no", normalize the case of
550          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
551          * This is in conflict with the current (3.0.20) man page, but is
552          * what people expect from the "large directory howto". I'll update
553          * the man page. Thanks to jht@samba.org for finding this. JRA.
554          */
555
556         if (conn->case_sensitive && !conn->case_preserve &&
557                         !conn->short_case_preserve) {
558                 if (!strnorm(smb_fname->base_name, lp_default_case(SNUM(conn)))) {
559                         DEBUG(0, ("strnorm %s failed\n", smb_fname->base_name));
560                         status = NT_STATUS_INVALID_PARAMETER;
561                         goto err;
562                 }
563         }
564
565         /*
566          * Ensure saved_last_component is valid even if file exists.
567          */
568
569         if(save_last_component) {
570                 end = strrchr_m(smb_fname->base_name, '/');
571                 if (end) {
572                         smb_fname->original_lcomp = talloc_strdup(smb_fname,
573                                                                   end + 1);
574                 } else {
575                         smb_fname->original_lcomp =
576                             talloc_strdup(smb_fname, smb_fname->base_name);
577                 }
578                 if (smb_fname->original_lcomp == NULL) {
579                         status = NT_STATUS_NO_MEMORY;
580                         goto err;
581                 }
582         }
583
584         /*
585          * Strip off the stream, and add it back when we're done with the
586          * base_name.
587          */
588         if (!posix_pathnames) {
589                 stream = strchr_m(smb_fname->base_name, ':');
590
591                 if (stream != NULL) {
592                         char *tmp = talloc_strdup(smb_fname, stream);
593                         if (tmp == NULL) {
594                                 status = NT_STATUS_NO_MEMORY;
595                                 goto err;
596                         }
597                         /*
598                          * Since this is actually pointing into
599                          * smb_fname->base_name this truncates base_name.
600                          */
601                         *stream = '\0';
602                         stream = tmp;
603
604                         if (smb_fname->base_name[0] == '\0') {
605                                 /*
606                                  * orig_name was just a stream name.
607                                  * This is a stream on the root of
608                                  * the share. Replace base_name with
609                                  * a "."
610                                  */
611                                 smb_fname->base_name =
612                                         talloc_strdup(smb_fname, ".");
613                                 if (smb_fname->base_name == NULL) {
614                                         status = NT_STATUS_NO_MEMORY;
615                                         goto err;
616                                 }
617                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
618                                         status = map_nt_error_from_unix(errno);
619                                         goto err;
620                                 }
621                                 /* dirpath must exist. */
622                                 dirpath = talloc_strdup(ctx,".");
623                                 if (dirpath == NULL) {
624                                         status = NT_STATUS_NO_MEMORY;
625                                         goto err;
626                                 }
627                                 DEBUG(5, ("conversion finished %s -> %s\n",
628                                         orig_path,
629                                         smb_fname->base_name));
630                                 goto done;
631                         }
632                 }
633         }
634
635         start = smb_fname->base_name;
636
637         /*
638          * If we're providing case insensitive semantics or
639          * the underlying filesystem is case insensitive,
640          * then a case-normalized hit in the stat-cache is
641          * authoratitive. JRA.
642          *
643          * Note: We're only checking base_name.  The stream_name will be
644          * added and verified in build_stream_path().
645          */
646
647         if((!conn->case_sensitive || !(conn->fs_capabilities &
648                                        FILE_CASE_SENSITIVE_SEARCH)) &&
649             stat_cache_lookup(conn, posix_pathnames, &smb_fname->base_name, &dirpath, &start,
650                               &smb_fname->st)) {
651                 goto done;
652         }
653
654         /*
655          * Make sure "dirpath" is an allocated string, we use this for
656          * building the directories with talloc_asprintf and free it.
657          */
658
659         if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,".")))) {
660                 DEBUG(0, ("talloc_strdup failed\n"));
661                 status = NT_STATUS_NO_MEMORY;
662                 goto err;
663         }
664
665         /*
666          * If we have a wildcard we must walk the path to
667          * find where the error is, even if case sensitive
668          * is true.
669          */
670
671         if (!posix_pathnames) {
672                 /* POSIX pathnames have no wildcards. */
673                 name_has_wildcard = ms_has_wild(smb_fname->base_name);
674                 if (name_has_wildcard && !allow_wcard_last_component) {
675                         /* Wildcard not valid anywhere. */
676                         status = NT_STATUS_OBJECT_NAME_INVALID;
677                         goto fail;
678                 }
679         }
680
681         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
682                  smb_fname->base_name, dirpath, start));
683
684         if (!name_has_wildcard) {
685                 /*
686                  * stat the name - if it exists then we can add the stream back (if
687                  * there was one) and be done!
688                  */
689
690                 if (posix_pathnames) {
691                         ret = SMB_VFS_LSTAT(conn, smb_fname);
692                 } else {
693                         ret = SMB_VFS_STAT(conn, smb_fname);
694                 }
695
696                 if (ret == 0) {
697                         status = check_for_dot_component(smb_fname);
698                         if (!NT_STATUS_IS_OK(status)) {
699                                 goto fail;
700                         }
701                         /* Add the path (not including the stream) to the cache. */
702                         stat_cache_add(orig_path, smb_fname->base_name,
703                                        conn->case_sensitive);
704                         DEBUG(5,("conversion of base_name finished %s -> %s\n",
705                                  orig_path, smb_fname->base_name));
706                         goto done;
707                 }
708
709                 /* Stat failed - ensure we don't use it. */
710                 SET_STAT_INVALID(smb_fname->st);
711
712                 if (errno == ENOENT) {
713                         /* Optimization when creating a new file - only
714                            the last component doesn't exist.
715                            NOTE : check_parent_exists() doesn't preserve errno.
716                         */
717                         int saved_errno = errno;
718                         status = check_parent_exists(ctx,
719                                                 conn,
720                                                 posix_pathnames,
721                                                 smb_fname,
722                                                 &dirpath,
723                                                 &start);
724                         errno = saved_errno;
725                         if (!NT_STATUS_IS_OK(status)) {
726                                 goto fail;
727                         }
728                 }
729
730                 /*
731                  * A special case - if we don't have any wildcards or mangling chars and are case
732                  * sensitive or the underlying filesystem is case insensitive then searching
733                  * won't help.
734                  */
735
736                 if ((conn->case_sensitive || !(conn->fs_capabilities &
737                                         FILE_CASE_SENSITIVE_SEARCH)) &&
738                                 !mangle_is_mangled(smb_fname->base_name, conn->params)) {
739
740                         status = check_for_dot_component(smb_fname);
741                         if (!NT_STATUS_IS_OK(status)) {
742                                 goto fail;
743                         }
744
745                         /*
746                          * The stat failed. Could be ok as it could be
747                          * a new file.
748                          */
749
750                         if (errno == ENOTDIR || errno == ELOOP) {
751                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
752                                 goto fail;
753                         } else if (errno == ENOENT) {
754                                 /*
755                                  * Was it a missing last component ?
756                                  * or a missing intermediate component ?
757                                  */
758                                 struct smb_filename parent_fname;
759                                 const char *last_component = NULL;
760
761                                 ZERO_STRUCT(parent_fname);
762                                 if (!parent_dirname(ctx, smb_fname->base_name,
763                                                         &parent_fname.base_name,
764                                                         &last_component)) {
765                                         status = NT_STATUS_NO_MEMORY;
766                                         goto fail;
767                                 }
768                                 if (posix_pathnames) {
769                                         ret = SMB_VFS_LSTAT(conn, &parent_fname);
770                                 } else {
771                                         ret = SMB_VFS_STAT(conn, &parent_fname);
772                                 }
773                                 if (ret == -1) {
774                                         if (errno == ENOTDIR ||
775                                                         errno == ENOENT ||
776                                                         errno == ELOOP) {
777                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
778                                                 goto fail;
779                                         }
780                                 }
781
782                                 /*
783                                  * Missing last component is ok - new file.
784                                  * Also deal with permission denied elsewhere.
785                                  * Just drop out to done.
786                                  */
787                                 goto done;
788                         }
789                 }
790         } else {
791                 /*
792                  * We have a wildcard in the pathname.
793                  *
794                  * Optimization for common case where the wildcard
795                  * is in the last component and the client already
796                  * sent the correct case.
797                  * NOTE : check_parent_exists() doesn't preserve errno.
798                  */
799                 int saved_errno = errno;
800                 status = check_parent_exists(ctx,
801                                         conn,
802                                         posix_pathnames,
803                                         smb_fname,
804                                         &dirpath,
805                                         &start);
806                 errno = saved_errno;
807                 if (!NT_STATUS_IS_OK(status)) {
808                         goto fail;
809                 }
810         }
811
812         /*
813          * is_mangled() was changed to look at an entire pathname, not
814          * just a component. JRA.
815          */
816
817         if (mangle_is_mangled(start, conn->params)) {
818                 component_was_mangled = True;
819         }
820
821         /*
822          * Now we need to recursively match the name against the real
823          * directory structure.
824          */
825
826         /*
827          * Match each part of the path name separately, trying the names
828          * as is first, then trying to scan the directory for matching names.
829          */
830
831         for (; start ; start = (end?end+1:(char *)NULL)) {
832                 /*
833                  * Pinpoint the end of this section of the filename.
834                  */
835                 /* mb safe. '/' can't be in any encoded char. */
836                 end = strchr(start, '/');
837
838                 /*
839                  * Chop the name at this point.
840                  */
841                 if (end) {
842                         *end = 0;
843                 }
844
845                 if (save_last_component) {
846                         TALLOC_FREE(smb_fname->original_lcomp);
847                         smb_fname->original_lcomp = talloc_strdup(smb_fname,
848                                                         end ? end + 1 : start);
849                         if (!smb_fname->original_lcomp) {
850                                 DEBUG(0, ("talloc failed\n"));
851                                 status = NT_STATUS_NO_MEMORY;
852                                 goto err;
853                         }
854                 }
855
856                 /* The name cannot have a component of "." */
857
858                 if (ISDOT(start)) {
859                         if (!end)  {
860                                 /* Error code at the end of a pathname. */
861                                 status = NT_STATUS_OBJECT_NAME_INVALID;
862                         } else {
863                                 status = determine_path_error(end+1,
864                                                 allow_wcard_last_component,
865                                                 posix_pathnames);
866                         }
867                         goto fail;
868                 }
869
870                 /* The name cannot have a wildcard if it's not
871                    the last component. */
872
873                 if (!posix_pathnames) {
874                         name_has_wildcard = ms_has_wild(start);
875                 }
876
877                 /* Wildcards never valid within a pathname. */
878                 if (name_has_wildcard && end) {
879                         status = NT_STATUS_OBJECT_NAME_INVALID;
880                         goto fail;
881                 }
882
883                 /* Skip the stat call if it's a wildcard end. */
884                 if (name_has_wildcard) {
885                         DEBUG(5,("Wildcard %s\n",start));
886                         goto done;
887                 }
888
889                 /*
890                  * Check if the name exists up to this point.
891                  */
892
893                 if (posix_pathnames) {
894                         ret = SMB_VFS_LSTAT(conn, smb_fname);
895                 } else {
896                         ret = SMB_VFS_STAT(conn, smb_fname);
897                 }
898
899                 if (ret == 0) {
900                         /*
901                          * It exists. it must either be a directory or this must
902                          * be the last part of the path for it to be OK.
903                          */
904                         if (end && !S_ISDIR(smb_fname->st.st_ex_mode)) {
905                                 /*
906                                  * An intermediate part of the name isn't
907                                  * a directory.
908                                  */
909                                 DEBUG(5,("Not a dir %s\n",start));
910                                 *end = '/';
911                                 /*
912                                  * We need to return the fact that the
913                                  * intermediate name resolution failed. This
914                                  * is used to return an error of ERRbadpath
915                                  * rather than ERRbadfile. Some Windows
916                                  * applications depend on the difference between
917                                  * these two errors.
918                                  */
919                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
920                                 goto fail;
921                         }
922
923                 } else {
924                         char *found_name = NULL;
925
926                         /* Stat failed - ensure we don't use it. */
927                         SET_STAT_INVALID(smb_fname->st);
928
929                         /*
930                          * Reset errno so we can detect
931                          * directory open errors.
932                          */
933                         errno = 0;
934
935                         /*
936                          * Try to find this part of the path in the directory.
937                          */
938
939                         if (name_has_wildcard ||
940                             (get_real_filename(conn, dirpath, start,
941                                                talloc_tos(),
942                                                &found_name) == -1)) {
943                                 char *unmangled;
944
945                                 if (end) {
946                                         /*
947                                          * An intermediate part of the name
948                                          * can't be found.
949                                          */
950                                         DEBUG(5,("Intermediate not found %s\n",
951                                                         start));
952                                         *end = '/';
953
954                                         /*
955                                          * We need to return the fact that the
956                                          * intermediate name resolution failed.
957                                          * This is used to return an error of
958                                          * ERRbadpath rather than ERRbadfile.
959                                          * Some Windows applications depend on
960                                          * the difference between these two
961                                          * errors.
962                                          */
963
964                                         /*
965                                          * ENOENT, ENOTDIR and ELOOP all map
966                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
967                                          * in the filename walk.
968                                          */
969
970                                         if (errno == ENOENT ||
971                                                         errno == ENOTDIR ||
972                                                         errno == ELOOP) {
973                                                 status =
974                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
975                                         }
976                                         else {
977                                                 status =
978                                                 map_nt_error_from_unix(errno);
979                                         }
980                                         goto fail;
981                                 }
982
983                                 /*
984                                  * ENOENT/EACCESS are the only valid errors
985                                  * here.
986                                  */
987
988                                 if (errno == EACCES) {
989                                         if ((ucf_flags & UCF_PREP_CREATEFILE) == 0) {
990                                                 status = NT_STATUS_ACCESS_DENIED;
991                                                 goto fail;
992                                         } else {
993                                                 /*
994                                                  * This is the dropbox
995                                                  * behaviour. A dropbox is a
996                                                  * directory with only -wx
997                                                  * permissions, so
998                                                  * get_real_filename fails
999                                                  * with EACCESS, it needs to
1000                                                  * list the directory. We
1001                                                  * nevertheless want to allow
1002                                                  * users creating a file.
1003                                                  */
1004                                                 errno = 0;
1005                                         }
1006                                 }
1007
1008                                 if ((errno != 0) && (errno != ENOENT)) {
1009                                         /*
1010                                          * ENOTDIR and ELOOP both map to
1011                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
1012                                          * in the filename walk.
1013                                          */
1014                                         if (errno == ENOTDIR ||
1015                                                         errno == ELOOP) {
1016                                                 status =
1017                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
1018                                         } else {
1019                                                 status =
1020                                                 map_nt_error_from_unix(errno);
1021                                         }
1022                                         goto fail;
1023                                 }
1024
1025                                 /*
1026                                  * Just the last part of the name doesn't exist.
1027                                  * We need to strupper() or strlower() it as
1028                                  * this conversion may be used for file creation
1029                                  * purposes. Fix inspired by
1030                                  * Thomas Neumann <t.neumann@iku-ag.de>.
1031                                  */
1032                                 if (!conn->case_preserve ||
1033                                     (mangle_is_8_3(start, False,
1034                                                    conn->params) &&
1035                                                  !conn->short_case_preserve)) {
1036                                         if (!strnorm(start,
1037                                                         lp_default_case(SNUM(conn)))) {
1038                                                 DEBUG(0, ("strnorm %s failed\n",
1039                                                         start));
1040                                                 status = NT_STATUS_INVALID_PARAMETER;
1041                                                 goto err;
1042                                         }
1043                                 }
1044
1045                                 /*
1046                                  * check on the mangled stack to see if we can
1047                                  * recover the base of the filename.
1048                                  */
1049
1050                                 if (mangle_is_mangled(start, conn->params)
1051                                     && mangle_lookup_name_from_8_3(ctx,
1052                                                         start,
1053                                                         &unmangled,
1054                                                         conn->params)) {
1055                                         char *tmp;
1056                                         size_t start_ofs =
1057                                             start - smb_fname->base_name;
1058
1059                                         if (!ISDOT(dirpath)) {
1060                                                 tmp = talloc_asprintf(
1061                                                         smb_fname, "%s/%s",
1062                                                         dirpath, unmangled);
1063                                                 TALLOC_FREE(unmangled);
1064                                         }
1065                                         else {
1066                                                 tmp = unmangled;
1067                                         }
1068                                         if (tmp == NULL) {
1069                                                 DEBUG(0, ("talloc failed\n"));
1070                                                 status = NT_STATUS_NO_MEMORY;
1071                                                 goto err;
1072                                         }
1073                                         TALLOC_FREE(smb_fname->base_name);
1074                                         smb_fname->base_name = tmp;
1075                                         start =
1076                                             smb_fname->base_name + start_ofs;
1077                                         end = start + strlen(start);
1078                                 }
1079
1080                                 DEBUG(5,("New file %s\n",start));
1081                                 goto done;
1082                         }
1083
1084
1085                         /*
1086                          * Restore the rest of the string. If the string was
1087                          * mangled the size may have changed.
1088                          */
1089                         if (end) {
1090                                 char *tmp;
1091                                 size_t start_ofs =
1092                                     start - smb_fname->base_name;
1093
1094                                 if (!ISDOT(dirpath)) {
1095                                         tmp = talloc_asprintf(smb_fname,
1096                                                 "%s/%s/%s", dirpath,
1097                                                 found_name, end+1);
1098                                 }
1099                                 else {
1100                                         tmp = talloc_asprintf(smb_fname,
1101                                                 "%s/%s", found_name,
1102                                                 end+1);
1103                                 }
1104                                 if (tmp == NULL) {
1105                                         DEBUG(0, ("talloc_asprintf failed\n"));
1106                                         status = NT_STATUS_NO_MEMORY;
1107                                         goto err;
1108                                 }
1109                                 TALLOC_FREE(smb_fname->base_name);
1110                                 smb_fname->base_name = tmp;
1111                                 start = smb_fname->base_name + start_ofs;
1112                                 end = start + strlen(found_name);
1113                                 *end = '\0';
1114                         } else {
1115                                 char *tmp;
1116                                 size_t start_ofs =
1117                                     start - smb_fname->base_name;
1118
1119                                 if (!ISDOT(dirpath)) {
1120                                         tmp = talloc_asprintf(smb_fname,
1121                                                 "%s/%s", dirpath,
1122                                                 found_name);
1123                                 } else {
1124                                         tmp = talloc_strdup(smb_fname,
1125                                                 found_name);
1126                                 }
1127                                 if (tmp == NULL) {
1128                                         DEBUG(0, ("talloc failed\n"));
1129                                         status = NT_STATUS_NO_MEMORY;
1130                                         goto err;
1131                                 }
1132                                 TALLOC_FREE(smb_fname->base_name);
1133                                 smb_fname->base_name = tmp;
1134                                 start = smb_fname->base_name + start_ofs;
1135
1136                                 /*
1137                                  * We just scanned for, and found the end of
1138                                  * the path. We must return a valid stat struct
1139                                  * if it exists. JRA.
1140                                  */
1141
1142                                 if (posix_pathnames) {
1143                                         ret = SMB_VFS_LSTAT(conn, smb_fname);
1144                                 } else {
1145                                         ret = SMB_VFS_STAT(conn, smb_fname);
1146                                 }
1147
1148                                 if (ret != 0) {
1149                                         SET_STAT_INVALID(smb_fname->st);
1150                                 }
1151                         }
1152
1153                         TALLOC_FREE(found_name);
1154                 } /* end else */
1155
1156                 /*
1157                  * Add to the dirpath that we have resolved so far.
1158                  */
1159
1160                 if (!ISDOT(dirpath)) {
1161                         char *tmp = talloc_asprintf(ctx,
1162                                         "%s/%s", dirpath, start);
1163                         if (!tmp) {
1164                                 DEBUG(0, ("talloc_asprintf failed\n"));
1165                                 status = NT_STATUS_NO_MEMORY;
1166                                 goto err;
1167                         }
1168                         TALLOC_FREE(dirpath);
1169                         dirpath = tmp;
1170                 }
1171                 else {
1172                         TALLOC_FREE(dirpath);
1173                         if (!(dirpath = talloc_strdup(ctx,start))) {
1174                                 DEBUG(0, ("talloc_strdup failed\n"));
1175                                 status = NT_STATUS_NO_MEMORY;
1176                                 goto err;
1177                         }
1178                 }
1179
1180                 /*
1181                  * Cache the dirpath thus far. Don't cache a name with mangled
1182                  * or wildcard components as this can change the size.
1183                  */
1184                 if(!component_was_mangled && !name_has_wildcard) {
1185                         stat_cache_add(orig_path, dirpath,
1186                                         conn->case_sensitive);
1187                 }
1188
1189                 /*
1190                  * Restore the / that we wiped out earlier.
1191                  */
1192                 if (end) {
1193                         *end = '/';
1194                 }
1195         }
1196
1197         /*
1198          * Cache the full path. Don't cache a name with mangled or wildcard
1199          * components as this can change the size.
1200          */
1201
1202         if(!component_was_mangled && !name_has_wildcard) {
1203                 stat_cache_add(orig_path, smb_fname->base_name,
1204                                conn->case_sensitive);
1205         }
1206
1207         /*
1208          * The name has been resolved.
1209          */
1210
1211         DEBUG(5,("conversion finished %s -> %s\n", orig_path,
1212                  smb_fname->base_name));
1213
1214  done:
1215         /* Add back the stream if one was stripped off originally. */
1216         if (stream != NULL) {
1217                 smb_fname->stream_name = stream;
1218
1219                 /* Check path now that the base_name has been converted. */
1220                 status = build_stream_path(ctx, conn, smb_fname);
1221                 if (!NT_STATUS_IS_OK(status)) {
1222                         goto fail;
1223                 }
1224         }
1225         TALLOC_FREE(dirpath);
1226         *smb_fname_out = smb_fname;
1227         return NT_STATUS_OK;
1228  fail:
1229         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
1230         if (dirpath && !ISDOT(dirpath)) {
1231                 smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
1232                                                        dirpath, start);
1233         } else {
1234                 smb_fname->base_name = talloc_strdup(smb_fname, start);
1235         }
1236         if (!smb_fname->base_name) {
1237                 DEBUG(0, ("talloc_asprintf failed\n"));
1238                 status = NT_STATUS_NO_MEMORY;
1239                 goto err;
1240         }
1241
1242         *smb_fname_out = smb_fname;
1243         TALLOC_FREE(dirpath);
1244         return status;
1245  err:
1246         TALLOC_FREE(smb_fname);
1247         return status;
1248 }
1249
1250 /****************************************************************************
1251  Ensure a path is not vetoed.
1252 ****************************************************************************/
1253
1254 static NTSTATUS check_veto_path(connection_struct *conn,
1255                         const struct smb_filename *smb_fname)
1256 {
1257         const char *name = smb_fname->base_name;
1258
1259         if (IS_VETO_PATH(conn, name))  {
1260                 /* Is it not dot or dot dot. */
1261                 if (!(ISDOT(name) || ISDOTDOT(name))) {
1262                         DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1263                                                 name));
1264                         return map_nt_error_from_unix(ENOENT);
1265                 }
1266         }
1267         return NT_STATUS_OK;
1268 }
1269
1270 /****************************************************************************
1271  Check a filename - possibly calling check_reduced_name.
1272  This is called by every routine before it allows an operation on a filename.
1273  It does any final confirmation necessary to ensure that the filename is
1274  a valid one for the user to access.
1275 ****************************************************************************/
1276
1277 NTSTATUS check_name(connection_struct *conn,
1278                         const struct smb_filename *smb_fname)
1279 {
1280         NTSTATUS status = check_veto_path(conn, smb_fname);
1281
1282         if (!NT_STATUS_IS_OK(status)) {
1283                 return status;
1284         }
1285
1286         if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
1287                 status = check_reduced_name(conn, NULL, smb_fname);
1288                 if (!NT_STATUS_IS_OK(status)) {
1289                         DEBUG(5,("check_name: name %s failed with %s\n",
1290                                         smb_fname->base_name,
1291                                         nt_errstr(status)));
1292                         return status;
1293                 }
1294         }
1295
1296         return NT_STATUS_OK;
1297 }
1298
1299 /****************************************************************************
1300  Must be called as root. Creates the struct privilege_paths
1301  attached to the struct smb_request if this call is successful.
1302 ****************************************************************************/
1303
1304 static NTSTATUS check_name_with_privilege(connection_struct *conn,
1305                 struct smb_request *smbreq,
1306                 const struct smb_filename *smb_fname)
1307 {
1308         NTSTATUS status = check_veto_path(conn, smb_fname);
1309
1310         if (!NT_STATUS_IS_OK(status)) {
1311                 return status;
1312         }
1313         return check_reduced_name_with_privilege(conn,
1314                         smb_fname,
1315                         smbreq);
1316 }
1317
1318 /****************************************************************************
1319  Check if two filenames are equal.
1320  This needs to be careful about whether we are case sensitive.
1321 ****************************************************************************/
1322
1323 static bool fname_equal(const char *name1, const char *name2,
1324                 bool case_sensitive)
1325 {
1326         /* Normal filename handling */
1327         if (case_sensitive) {
1328                 return(strcmp(name1,name2) == 0);
1329         }
1330
1331         return(strequal(name1,name2));
1332 }
1333
1334 /****************************************************************************
1335  Scan a directory to find a filename, matching without case sensitivity.
1336  If the name looks like a mangled name then try via the mangling functions
1337 ****************************************************************************/
1338
1339 static int get_real_filename_full_scan(connection_struct *conn,
1340                                        const char *path, const char *name,
1341                                        bool mangled,
1342                                        TALLOC_CTX *mem_ctx, char **found_name)
1343 {
1344         struct smb_Dir *cur_dir;
1345         const char *dname = NULL;
1346         char *talloced = NULL;
1347         char *unmangled_name = NULL;
1348         long curpos;
1349         struct smb_filename *smb_fname = NULL;
1350
1351         /* handle null paths */
1352         if ((path == NULL) || (*path == 0)) {
1353                 path = ".";
1354         }
1355
1356         /* If we have a case-sensitive filesystem, it doesn't do us any
1357          * good to search for a name. If a case variation of the name was
1358          * there, then the original stat(2) would have found it.
1359          */
1360         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
1361                 errno = ENOENT;
1362                 return -1;
1363         }
1364
1365         /*
1366          * The incoming name can be mangled, and if we de-mangle it
1367          * here it will not compare correctly against the filename (name2)
1368          * read from the directory and then mangled by the name_to_8_3()
1369          * call. We need to mangle both names or neither.
1370          * (JRA).
1371          *
1372          * Fix for bug found by Dina Fine. If in case sensitive mode then
1373          * the mangle cache is no good (3 letter extension could be wrong
1374          * case - so don't demangle in this case - leave as mangled and
1375          * allow the mangling of the directory entry read (which is done
1376          * case insensitively) to match instead. This will lead to more
1377          * false positive matches but we fail completely without it. JRA.
1378          */
1379
1380         if (mangled && !conn->case_sensitive) {
1381                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
1382                                                        &unmangled_name,
1383                                                        conn->params);
1384                 if (!mangled) {
1385                         /* Name is now unmangled. */
1386                         name = unmangled_name;
1387                 }
1388         }
1389
1390         smb_fname = synthetic_smb_fname(talloc_tos(),
1391                                         path,
1392                                         NULL,
1393                                         NULL,
1394                                         0);
1395         if (smb_fname == NULL) {
1396                 TALLOC_FREE(unmangled_name);
1397                 return -1;
1398         }
1399
1400         /* open the directory */
1401         if (!(cur_dir = OpenDir(talloc_tos(), conn, smb_fname, NULL, 0))) {
1402                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
1403                 TALLOC_FREE(unmangled_name);
1404                 TALLOC_FREE(smb_fname);
1405                 return -1;
1406         }
1407
1408         TALLOC_FREE(smb_fname);
1409
1410         /* now scan for matching names */
1411         curpos = 0;
1412         while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
1413
1414                 /* Is it dot or dot dot. */
1415                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1416                         TALLOC_FREE(talloced);
1417                         continue;
1418                 }
1419
1420                 /*
1421                  * At this point dname is the unmangled name.
1422                  * name is either mangled or not, depending on the state
1423                  * of the "mangled" variable. JRA.
1424                  */
1425
1426                 /*
1427                  * Check mangled name against mangled name, or unmangled name
1428                  * against unmangled name.
1429                  */
1430
1431                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
1432                         fname_equal(name, dname, conn->case_sensitive)) {
1433                         /* we've found the file, change it's name and return */
1434                         *found_name = talloc_strdup(mem_ctx, dname);
1435                         TALLOC_FREE(unmangled_name);
1436                         TALLOC_FREE(cur_dir);
1437                         if (!*found_name) {
1438                                 errno = ENOMEM;
1439                                 TALLOC_FREE(talloced);
1440                                 return -1;
1441                         }
1442                         TALLOC_FREE(talloced);
1443                         return 0;
1444                 }
1445                 TALLOC_FREE(talloced);
1446         }
1447
1448         TALLOC_FREE(unmangled_name);
1449         TALLOC_FREE(cur_dir);
1450         errno = ENOENT;
1451         return -1;
1452 }
1453
1454 /****************************************************************************
1455  Wrapper around the vfs get_real_filename and the full directory scan
1456  fallback.
1457 ****************************************************************************/
1458
1459 int get_real_filename(connection_struct *conn, const char *path,
1460                       const char *name, TALLOC_CTX *mem_ctx,
1461                       char **found_name)
1462 {
1463         int ret;
1464         bool mangled;
1465
1466         /* handle null paths */
1467         if ((path == NULL) || (*path == 0)) {
1468                 path = ".";
1469         }
1470
1471         mangled = mangle_is_mangled(name, conn->params);
1472
1473         if (mangled) {
1474                 return get_real_filename_full_scan(conn, path, name, mangled,
1475                                                    mem_ctx, found_name);
1476         }
1477
1478         /* Try the vfs first to take advantage of case-insensitive stat. */
1479         ret = SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name);
1480
1481         /*
1482          * If the case-insensitive stat was successful, or returned an error
1483          * other than EOPNOTSUPP then there is no need to fall back on the
1484          * full directory scan.
1485          */
1486         if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
1487                 return ret;
1488         }
1489
1490         return get_real_filename_full_scan(conn, path, name, mangled, mem_ctx,
1491                                            found_name);
1492 }
1493
1494 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1495                                   connection_struct *conn,
1496                                   struct smb_filename *smb_fname)
1497 {
1498         NTSTATUS status;
1499         unsigned int i, num_streams = 0;
1500         struct stream_struct *streams = NULL;
1501
1502         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1503                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1504                 return NT_STATUS_OK;
1505         }
1506
1507         if (errno != ENOENT) {
1508                 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1509                 status = map_nt_error_from_unix(errno);
1510                 goto fail;
1511         }
1512
1513         /* Fall back to a case-insensitive scan of all streams on the file. */
1514         status = vfs_streaminfo(conn, NULL, smb_fname, mem_ctx,
1515                                 &num_streams, &streams);
1516
1517         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1518                 SET_STAT_INVALID(smb_fname->st);
1519                 return NT_STATUS_OK;
1520         }
1521
1522         if (!NT_STATUS_IS_OK(status)) {
1523                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
1524                 goto fail;
1525         }
1526
1527         for (i=0; i<num_streams; i++) {
1528                 DEBUG(10, ("comparing [%s] and [%s]: ",
1529                            smb_fname->stream_name, streams[i].name));
1530                 if (fname_equal(smb_fname->stream_name, streams[i].name,
1531                                 conn->case_sensitive)) {
1532                         DEBUGADD(10, ("equal\n"));
1533                         break;
1534                 }
1535                 DEBUGADD(10, ("not equal\n"));
1536         }
1537
1538         /* Couldn't find the stream. */
1539         if (i == num_streams) {
1540                 SET_STAT_INVALID(smb_fname->st);
1541                 TALLOC_FREE(streams);
1542                 return NT_STATUS_OK;
1543         }
1544
1545         DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1546                 smb_fname->stream_name, streams[i].name));
1547
1548
1549         TALLOC_FREE(smb_fname->stream_name);
1550         smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
1551         if (smb_fname->stream_name == NULL) {
1552                 status = NT_STATUS_NO_MEMORY;
1553                 goto fail;
1554         }
1555
1556         SET_STAT_INVALID(smb_fname->st);
1557
1558         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1559                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1560         }
1561         status = NT_STATUS_OK;
1562  fail:
1563         TALLOC_FREE(streams);
1564         return status;
1565 }
1566
1567 /**
1568  * Go through all the steps to validate a filename.
1569  *
1570  * @param ctx           talloc_ctx to allocate memory with.
1571  * @param conn          connection struct for vfs calls.
1572  * @param smbreq        SMB request if we're using privileges.
1573  * @param name_in       The unconverted name.
1574  * @param ucf_flags     flags to pass through to unix_convert().
1575  *                      UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
1576  *                      p_cont_wcard != NULL and is true and
1577  *                      UCF_COND_ALLOW_WCARD_LCOMP.
1578  * @param p_cont_wcard  If not NULL, will be set to true if the dfs path
1579  *                      resolution detects a wildcard.
1580  * @param pp_smb_fname  The final converted name will be allocated if the
1581  *                      return is NT_STATUS_OK.
1582  *
1583  * @return NT_STATUS_OK if all operations completed successfully, appropriate
1584  *         error otherwise.
1585  */
1586 static NTSTATUS filename_convert_internal(TALLOC_CTX *ctx,
1587                                 connection_struct *conn,
1588                                 struct smb_request *smbreq,
1589                                 const char *name_in,
1590                                 uint32_t ucf_flags,
1591                                 bool *ppath_contains_wcard,
1592                                 struct smb_filename **pp_smb_fname)
1593 {
1594         NTSTATUS status;
1595
1596         *pp_smb_fname = NULL;
1597
1598         if (ucf_flags & UCF_DFS_PATHNAME) {
1599                 bool path_contains_wcard = false;
1600                 char *fname = NULL;
1601                 status = resolve_dfspath_wcard(ctx, conn,
1602                                 name_in,
1603                                 ucf_flags,
1604                                 !conn->sconn->using_smb2,
1605                                 &fname,
1606                                 &path_contains_wcard);
1607                 if (!NT_STATUS_IS_OK(status)) {
1608                         DEBUG(10,("filename_convert_internal: resolve_dfspath "
1609                                 "failed for name %s with %s\n",
1610                                 name_in,
1611                                 nt_errstr(status) ));
1612                         return status;
1613                 }
1614                 name_in = fname;
1615                 if (ppath_contains_wcard != NULL && path_contains_wcard) {
1616                         *ppath_contains_wcard = path_contains_wcard;
1617                 }
1618                 ucf_flags &= ~UCF_DFS_PATHNAME;
1619         }
1620
1621         if (is_fake_file_path(name_in)) {
1622                 SMB_STRUCT_STAT st;
1623                 ZERO_STRUCT(st);
1624                 st.st_ex_nlink = 1;
1625                 *pp_smb_fname = synthetic_smb_fname_split(ctx,
1626                                         name_in,
1627                                         (ucf_flags & UCF_POSIX_PATHNAMES));
1628                 if (*pp_smb_fname == NULL) {
1629                         return NT_STATUS_NO_MEMORY;
1630                 }
1631                 (*pp_smb_fname)->st = st;
1632                 return NT_STATUS_OK;
1633         }
1634
1635         /*
1636          * If the caller conditionally allows wildcard lookups, only add the
1637          * always allow if the path actually does contain a wildcard.
1638          */
1639         if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
1640             ppath_contains_wcard != NULL && *ppath_contains_wcard) {
1641                 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
1642         }
1643
1644         status = unix_convert(ctx, conn, name_in, pp_smb_fname, ucf_flags);
1645         if (!NT_STATUS_IS_OK(status)) {
1646                 DEBUG(10,("filename_convert_internal: unix_convert failed "
1647                         "for name %s with %s\n",
1648                         name_in,
1649                         nt_errstr(status) ));
1650                 return status;
1651         }
1652
1653         if ((ucf_flags & UCF_UNIX_NAME_LOOKUP) &&
1654                         VALID_STAT((*pp_smb_fname)->st) &&
1655                         S_ISLNK((*pp_smb_fname)->st.st_ex_mode)) {
1656                 return check_veto_path(conn, (*pp_smb_fname));
1657         }
1658
1659         if (!smbreq) {
1660                 status = check_name(conn, (*pp_smb_fname));
1661         } else {
1662                 status = check_name_with_privilege(conn, smbreq,
1663                                 (*pp_smb_fname));
1664         }
1665         if (!NT_STATUS_IS_OK(status)) {
1666                 DEBUG(3,("filename_convert_internal: check_name failed "
1667                         "for name %s with %s\n",
1668                         smb_fname_str_dbg(*pp_smb_fname),
1669                         nt_errstr(status) ));
1670                 TALLOC_FREE(*pp_smb_fname);
1671                 return status;
1672         }
1673
1674         return status;
1675 }
1676
1677 /*
1678  * Go through all the steps to validate a filename.
1679  * Non-root version.
1680  */
1681
1682 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1683                                 connection_struct *conn,
1684                                 const char *name_in,
1685                                 uint32_t ucf_flags,
1686                                 bool *ppath_contains_wcard,
1687                                 struct smb_filename **pp_smb_fname)
1688 {
1689         return filename_convert_internal(ctx,
1690                                         conn,
1691                                         NULL,
1692                                         name_in,
1693                                         ucf_flags,
1694                                         ppath_contains_wcard,
1695                                         pp_smb_fname);
1696 }
1697
1698 /*
1699  * Go through all the steps to validate a filename.
1700  * root (privileged) version.
1701  */
1702
1703 NTSTATUS filename_convert_with_privilege(TALLOC_CTX *ctx,
1704                                 connection_struct *conn,
1705                                 struct smb_request *smbreq,
1706                                 const char *name_in,
1707                                 uint32_t ucf_flags,
1708                                 bool *ppath_contains_wcard,
1709                                 struct smb_filename **pp_smb_fname)
1710 {
1711         return filename_convert_internal(ctx,
1712                                         conn,
1713                                         smbreq,
1714                                         name_in,
1715                                         ucf_flags,
1716                                         ppath_contains_wcard,
1717                                         pp_smb_fname);
1718 }