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