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