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