r23844: Add patch series from Volker (after review and consultation).
[samba.git] / source / 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-2004
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
29 static BOOL scan_directory(connection_struct *conn, const char *path,
30                            char *name, char **found_name);
31
32 /****************************************************************************
33  Mangle the 2nd name and check if it is then equal to the first name.
34 ****************************************************************************/
35
36 static BOOL mangled_equal(const char *name1, const char *name2,
37                           const struct share_params *p)
38 {
39         pstring tmpname;
40         
41         pstrcpy(tmpname, name2);
42         mangle_map(tmpname, True, False, p);
43         return strequal(name1, tmpname);
44 }
45
46 /****************************************************************************
47  Cope with the differing wildcard and non-wildcard error cases.
48 ****************************************************************************/
49
50 static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_component)
51 {
52         const char *p;
53
54         if (!allow_wcard_last_component) {
55                 /* Error code within a pathname. */
56                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
57         }
58
59         /* We're terminating here so we
60          * can be a little slower and get
61          * the error code right. Windows
62          * treats the last part of the pathname
63          * separately I think, so if the last
64          * component is a wildcard then we treat
65          * this ./ as "end of component" */
66
67         p = strchr(name, '/');
68
69         if (!p && (ms_has_wild(name) || ISDOT(name))) {
70                 /* Error code at the end of a pathname. */
71                 return NT_STATUS_OBJECT_NAME_INVALID;
72         } else {
73                 /* Error code within a pathname. */
74                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
75         }
76 }
77         
78 /****************************************************************************
79 This routine is called to convert names from the dos namespace to unix
80 namespace. It needs to handle any case conversions, mangling, format
81 changes etc.
82
83 We assume that we have already done a chdir() to the right "root" directory
84 for this service.
85
86 The function will return an NTSTATUS error if some part of the name except for the last
87 part cannot be resolved, else NT_STATUS_OK.
88
89 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
90 get any fatal errors that should immediately terminate the calling
91 SMB processing whilst resolving.
92
93 If the saved_last_component != 0, then the unmodified last component
94 of the pathname is returned there. This is used in an exceptional
95 case in reply_mv (so far). If saved_last_component == 0 then nothing
96 is returned there.
97
98 If last_component_wcard is true then a MS wildcard was detected and
99 should be allowed in the last component of the path only.
100
101 On exit from unix_convert, if *pst was not null, then the file stat
102 struct will be returned if the file exists and was found, if not this
103 stat struct will be filled with zeros (and this can be detected by checking
104 for nlinks = 0, which can never be true for any file).
105 ****************************************************************************/
106
107 NTSTATUS unix_convert(connection_struct *conn,
108                         pstring orig_path,
109                         BOOL allow_wcard_last_component,
110                         char *saved_last_component,
111                         SMB_STRUCT_STAT *pst)
112 {
113         SMB_STRUCT_STAT st;
114         char *start, *end;
115         char *dirpath = NULL;
116         char *name = NULL;
117         BOOL component_was_mangled = False;
118         BOOL name_has_wildcard = False;
119         NTSTATUS result;
120
121         SET_STAT_INVALID(*pst);
122
123         if(saved_last_component) {
124                 *saved_last_component = 0;
125         }
126
127         if (conn->printer) {
128                 /* we don't ever use the filenames on a printer share as a
129                         filename - so don't convert them */
130                 return NT_STATUS_OK;
131         }
132
133         DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
134
135         /*
136          * Conversion to basic unix format is already done in check_path_syntax().
137          */
138
139         /*
140          * Names must be relative to the root of the service - any leading /.
141          * and trailing /'s should have been trimmed by check_path_syntax().
142          */
143
144 #ifdef DEVELOPER
145         SMB_ASSERT(*orig_path != '/');
146 #endif
147
148         /*
149          * If we trimmed down to a single '\0' character
150          * then we should use the "." directory to avoid
151          * searching the cache, but not if we are in a
152          * printing share.
153          * As we know this is valid we can return true here.
154          */
155
156         if (!*orig_path) {
157                 if (!(name = SMB_STRDUP("."))) {
158                         result = NT_STATUS_NO_MEMORY;
159                         goto fail;
160                 }
161                 if (SMB_VFS_STAT(conn,name,&st) == 0) {
162                         *pst = st;
163                 }
164                 DEBUG(5,("conversion finished \"\" -> %s\n",name));
165                 goto done;
166         }
167
168         if (orig_path[0] == '.' && (orig_path[1] == '/' || orig_path[1] == '\0')) {
169                 /* Start of pathname can't be "." only. */
170                 if (orig_path[1] == '\0' || orig_path[2] == '\0') {
171                         result = NT_STATUS_OBJECT_NAME_INVALID;
172                 } else {
173                         result =determine_path_error(
174                                 &orig_path[2], allow_wcard_last_component);
175                 }
176                 goto fail;
177         }
178
179         /*
180          * Ensure saved_last_component is valid even if file exists.
181          */
182
183         if(saved_last_component) {
184                 end = strrchr_m(orig_path, '/');
185                 if (end) {
186                         pstrcpy(saved_last_component, end + 1);
187                 } else {
188                         pstrcpy(saved_last_component, orig_path);
189                 }
190         }
191
192         if (!(name = SMB_STRDUP(orig_path))) {
193                 DEBUG(0, ("strdup failed\n"));
194                 return NT_STATUS_NO_MEMORY;
195         }
196
197         /*
198          * Large directory fix normalization. If we're case sensitive, and
199          * the case preserving parameters are set to "no", normalize the case of
200          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
201          * This is in conflict with the current (3.0.20) man page, but is
202          * what people expect from the "large directory howto". I'll update
203          * the man page. Thanks to jht@samba.org for finding this. JRA.
204          */
205
206         if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) {
207                 strnorm(name, lp_defaultcase(SNUM(conn)));
208         }
209
210         start = name;
211
212         if(!conn->case_sensitive
213            && stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
214                 *pst = st;
215                 goto done;
216         }
217
218         /*
219          * Make sure "dirpath" is an allocated string, we use this for
220          * building the directories with asprintf and free it.
221          */
222
223         if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) {
224                 DEBUG(0, ("strdup failed\n"));
225                 result = NT_STATUS_NO_MEMORY;
226                 goto fail;
227         }
228
229         /*
230          * stat the name - if it exists then we are all done!
231          */
232
233         if (SMB_VFS_STAT(conn,name,&st) == 0) {
234                 /* Ensure we catch all names with in "/."
235                    this is disallowed under Windows. */
236                 const char *p = strstr(name, "/."); /* mb safe. */
237                 if (p) {
238                         if (p[2] == '/') {
239                                 /* Error code within a pathname. */
240                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
241                         } else if (p[2] == '\0') {
242                                 /* Error code at the end of a pathname. */
243                                 return NT_STATUS_OBJECT_NAME_INVALID;
244                         }
245                 }
246                 stat_cache_add(orig_path, name, conn->case_sensitive);
247                 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
248                 *pst = st;
249                 goto done;
250         }
251
252         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
253
254         /*
255          * A special case - if we don't have any mangling chars and are case
256          * sensitive then searching won't help.
257          */
258
259         if (conn->case_sensitive &&
260                         !mangle_is_mangled(name, conn->params) &&
261                         !*lp_mangled_map(conn->params)) {
262                 goto done;
263         }
264
265         /*
266          * is_mangled() was changed to look at an entire pathname, not
267          * just a component. JRA.
268          */
269
270         if (mangle_is_mangled(start, conn->params)) {
271                 component_was_mangled = True;
272         }
273
274         /*
275          * Now we need to recursively match the name against the real
276          * directory structure.
277          */
278
279         /*
280          * Match each part of the path name separately, trying the names
281          * as is first, then trying to scan the directory for matching names.
282          */
283
284         for (; start ; start = (end?end+1:(char *)NULL)) {
285                 /*
286                  * Pinpoint the end of this section of the filename.
287                  */
288                 end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */
289
290                 /*
291                  * Chop the name at this point.
292                  */
293                 if (end) {
294                         *end = 0;
295                 }
296
297                 if (saved_last_component != 0) {
298                         pstrcpy(saved_last_component, end ? end + 1 : start);
299                 }
300
301                 /* The name cannot have a component of "." */
302
303                 if (ISDOT(start)) {
304                         if (!end)  {
305                                 /* Error code at the end of a pathname. */
306                                 result = NT_STATUS_OBJECT_NAME_INVALID;
307                         } else {
308                                 result = determine_path_error(end+1,
309                                                 allow_wcard_last_component);
310                         }
311                         goto fail;
312                 }
313
314                 /* The name cannot have a wildcard if it's not
315                    the last component. */
316
317                 name_has_wildcard = ms_has_wild(start);
318
319                 /* Wildcard not valid anywhere. */
320                 if (name_has_wildcard && !allow_wcard_last_component) {
321                         result = NT_STATUS_OBJECT_NAME_INVALID;
322                         goto fail;
323                 }
324
325                 /* Wildcards never valid within a pathname. */
326                 if (name_has_wildcard && end) {
327                         result = NT_STATUS_OBJECT_NAME_INVALID;
328                         goto fail;
329                 }
330
331                 /*
332                  * Check if the name exists up to this point.
333                  */
334
335                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
336                         /*
337                          * It exists. it must either be a directory or this must be
338                          * the last part of the path for it to be OK.
339                          */
340                         if (end && !(st.st_mode & S_IFDIR)) {
341                                 /*
342                                  * An intermediate part of the name isn't a directory.
343                                  */
344                                 DEBUG(5,("Not a dir %s\n",start));
345                                 *end = '/';
346                                 /*
347                                  * We need to return the fact that the intermediate
348                                  * name resolution failed. This is used to return an
349                                  * error of ERRbadpath rather than ERRbadfile. Some
350                                  * Windows applications depend on the difference between
351                                  * these two errors.
352                                  */
353                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
354                                 goto fail;
355                         }
356
357                         if (!end) {
358                                 /*
359                                  * We just scanned for, and found the end of the path.
360                                  * We must return the valid stat struct.
361                                  * JRA.
362                                  */
363
364                                 *pst = st;
365                         }
366
367                 } else {
368                         char *found_name = NULL;
369
370                         /* Stat failed - ensure we don't use it. */
371                         SET_STAT_INVALID(st);
372
373                         /* Reset errno so we can detect directory open errors. */
374                         errno = 0;
375
376                         /*
377                          * Try to find this part of the path in the directory.
378                          */
379
380                         if (name_has_wildcard || 
381                             !scan_directory(conn, dirpath, start, &found_name)) {
382                                 char *unmangled;
383
384                                 if (end) {
385                                         /*
386                                          * An intermediate part of the name can't be found.
387                                          */
388                                         DEBUG(5,("Intermediate not found %s\n",start));
389                                         *end = '/';
390
391                                         /*
392                                          * We need to return the fact that the intermediate
393                                          * name resolution failed. This is used to return an
394                                          * error of ERRbadpath rather than ERRbadfile. Some
395                                          * Windows applications depend on the difference between
396                                          * these two errors.
397                                          */
398
399                                         /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND
400                                            in the filename walk. */
401
402                                         if (errno == ENOENT || errno == ENOTDIR) {
403                                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
404                                         }
405                                         else {
406                                                 result = map_nt_error_from_unix(errno);
407                                         }
408                                         goto fail;
409                                 }
410
411                                 /* ENOENT is the only valid error here. */
412                                 if (errno != ENOENT) {
413                                         /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND
414                                            in the filename walk. */
415                                         if (errno == ENOTDIR) {
416                                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
417                                         }
418                                         else {
419                                                 result = map_nt_error_from_unix(errno);
420                                         }
421                                         goto fail;
422                                 }
423
424                                 /*
425                                  * Just the last part of the name doesn't exist.
426                                  * We need to strupper() or strlower() it as
427                                  * this conversion may be used for file creation 
428                                  * purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>.
429                                  */
430                                 if (!conn->case_preserve ||
431                                     (mangle_is_8_3(start, False, conn->params) &&
432                                                  !conn->short_case_preserve)) {
433                                         strnorm(start, lp_defaultcase(SNUM(conn)));
434                                 }
435
436                                 /*
437                                  * check on the mangled stack to see if we can recover the 
438                                  * base of the filename.
439                                  */
440
441                                 if (mangle_is_mangled(start, conn->params)
442                                     && mangle_check_cache_alloc(start, &unmangled,
443                                                                 conn->params)) {
444                                         char *tmp;
445                                         size_t start_ofs = start - name;
446
447                                         if (*dirpath != '\0') {
448                                                 asprintf(&tmp, "%s/%s", dirpath,
449                                                          unmangled);
450                                                 SAFE_FREE(unmangled);
451                                         }
452                                         else {
453                                                 tmp = unmangled;
454                                         }
455                                         if (tmp == NULL) {
456                                                 DEBUG(0, ("malloc failed\n"));
457                                                 result = NT_STATUS_NO_MEMORY;
458                                         }
459                                         SAFE_FREE(name);
460                                         name = tmp;
461                                         start = name + start_ofs;
462                                         end = start + strlen(start);
463                                 }
464
465                                 DEBUG(5,("New file %s\n",start));
466                                 goto done;
467                         }
468
469
470                         /*
471                          * Restore the rest of the string. If the string was mangled the size
472                          * may have changed.
473                          */
474                         if (end) {
475                                 char *tmp;
476                                 size_t start_ofs = start - name;
477
478                                 if (*dirpath != '\0') {
479                                         asprintf(&tmp, "%s/%s/%s", dirpath,
480                                                  found_name, end+1);
481                                 }
482                                 else {
483                                         asprintf(&tmp, "%s/%s", found_name,
484                                                  end+1);
485                                 }
486                                 if (tmp == NULL) {
487                                         DEBUG(0, ("asprintf failed\n"));
488                                         result = NT_STATUS_NO_MEMORY;
489                                 }
490                                 SAFE_FREE(name);
491                                 name = tmp;
492                                 start = name + start_ofs;
493                                 end = start + strlen(found_name);
494                                 *end = '\0';
495                         } else {
496                                 char *tmp;
497                                 size_t start_ofs = start - name;
498
499                                 if (*dirpath != '\0') {
500                                         asprintf(&tmp, "%s/%s", dirpath,
501                                                  found_name);
502                                 }
503                                 else {
504                                         tmp = SMB_STRDUP(found_name);
505                                 }
506                                 if (tmp == NULL) {
507                                         DEBUG(0, ("malloc failed\n"));
508                                         result = NT_STATUS_NO_MEMORY;
509                                 }
510                                 SAFE_FREE(name);
511                                 name = tmp;
512                                 start = name + start_ofs;
513
514                                 /*
515                                  * We just scanned for, and found the end of the path.
516                                  * We must return a valid stat struct if it exists.
517                                  * JRA.
518                                  */
519
520                                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
521                                         *pst = st;
522                                 } else {
523                                         SET_STAT_INVALID(st);
524                                 }
525                         }
526
527                         SAFE_FREE(found_name);
528                 } /* end else */
529
530 #ifdef DEVELOPER
531                 if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) {
532                         result = NT_STATUS_DELETE_PENDING;
533                         goto fail;
534                 }
535 #endif
536
537                 /* 
538                  * Add to the dirpath that we have resolved so far.
539                  */
540
541                 if (*dirpath != '\0') {
542                         char *tmp;
543
544                         if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) {
545                                 DEBUG(0, ("asprintf failed\n"));
546                                 return NT_STATUS_NO_MEMORY;
547                         }
548                         SAFE_FREE(dirpath);
549                         dirpath = tmp;
550                 }
551                 else {
552                         SAFE_FREE(dirpath);
553                         if (!(dirpath = SMB_STRDUP(start))) {
554                                 DEBUG(0, ("strdup failed\n"));
555                                 return NT_STATUS_NO_MEMORY;
556                         }
557                 }
558
559                 /*
560                  * Don't cache a name with mangled or wildcard components
561                  * as this can change the size.
562                  */
563
564                 if(!component_was_mangled && !name_has_wildcard) {
565                         stat_cache_add(orig_path, dirpath, conn->case_sensitive);
566                 }
567
568                 /*
569                  * Restore the / that we wiped out earlier.
570                  */
571                 if (end) {
572                         *end = '/';
573                 }
574         }
575
576         /*
577          * Don't cache a name with mangled or wildcard components
578          * as this can change the size.
579          */
580
581         if(!component_was_mangled && !name_has_wildcard) {
582                 stat_cache_add(orig_path, name, conn->case_sensitive);
583         }
584
585         /*
586          * The name has been resolved.
587          */
588
589         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
590
591  done:
592         result = NT_STATUS_OK;
593         pstrcpy(orig_path, name);
594  fail:
595         SAFE_FREE(name);
596         SAFE_FREE(dirpath);
597         return result;
598 }
599
600 /****************************************************************************
601  Check a filename - possibly calling check_reduced_name.
602  This is called by every routine before it allows an operation on a filename.
603  It does any final confirmation necessary to ensure that the filename is
604  a valid one for the user to access.
605 ****************************************************************************/
606
607 NTSTATUS check_name(connection_struct *conn, const pstring name)
608 {
609         if (IS_VETO_PATH(conn, name))  {
610                 /* Is it not dot or dot dot. */
611                 if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
612                         DEBUG(5,("check_name: file path name %s vetoed\n",name));
613                         return map_nt_error_from_unix(ENOENT);
614                 }
615         }
616
617         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
618                 NTSTATUS status = check_reduced_name(conn,name);
619                 if (!NT_STATUS_IS_OK(status)) {
620                         DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status)));
621                         return status;
622                 }
623         }
624
625         return NT_STATUS_OK;
626 }
627
628 /****************************************************************************
629  Check if two filenames are equal.
630  This needs to be careful about whether we are case sensitive.
631 ****************************************************************************/
632
633 static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive)
634 {
635         /* Normal filename handling */
636         if (case_sensitive)
637                 return(strcmp(name1,name2) == 0);
638
639         return(strequal(name1,name2));
640 }
641
642 /****************************************************************************
643  Scan a directory to find a filename, matching without case sensitivity.
644  If the name looks like a mangled name then try via the mangling functions
645 ****************************************************************************/
646
647 static BOOL scan_directory(connection_struct *conn, const char *path,
648                            char *name, char **found_name)
649 {
650         struct smb_Dir *cur_dir;
651         const char *dname;
652         BOOL mangled;
653         char *unmangled_name = NULL;
654         long curpos;
655
656         mangled = mangle_is_mangled(name, conn->params);
657
658         /* handle null paths */
659         if ((path == NULL) || (*path == 0))
660                 path = ".";
661
662         /*
663          * The incoming name can be mangled, and if we de-mangle it
664          * here it will not compare correctly against the filename (name2)
665          * read from the directory and then mangled by the mangle_map()
666          * call. We need to mangle both names or neither.
667          * (JRA).
668          *
669          * Fix for bug found by Dina Fine. If in case sensitive mode then
670          * the mangle cache is no good (3 letter extension could be wrong
671          * case - so don't demangle in this case - leave as mangled and
672          * allow the mangling of the directory entry read (which is done
673          * case insensitively) to match instead. This will lead to more
674          * false positive matches but we fail completely without it. JRA.
675          */
676
677         if (mangled && !conn->case_sensitive) {
678                 mangled = !mangle_check_cache_alloc(name, &unmangled_name,
679                                                     conn->params);
680                 name = unmangled_name;
681         }
682
683         /* open the directory */
684         if (!(cur_dir = OpenDir(conn, path, NULL, 0))) {
685                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
686                 SAFE_FREE(unmangled_name);
687                 return(False);
688         }
689
690         /* now scan for matching names */
691         curpos = 0;
692         while ((dname = ReadDirName(cur_dir, &curpos))) {
693
694                 /* Is it dot or dot dot. */
695                 if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) {
696                         continue;
697                 }
698
699                 /*
700                  * At this point dname is the unmangled name.
701                  * name is either mangled or not, depending on the state of the "mangled"
702                  * variable. JRA.
703                  */
704
705                 /*
706                  * Check mangled name against mangled name, or unmangled name
707                  * against unmangled name.
708                  */
709
710                 if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) {
711                         /* we've found the file, change it's name and return */
712                         *found_name = SMB_STRDUP(dname);
713                         SAFE_FREE(unmangled_name);
714                         CloseDir(cur_dir);
715                         return(True);
716                 }
717         }
718
719         SAFE_FREE(unmangled_name);
720         CloseDir(cur_dir);
721         errno = ENOENT;
722         return(False);
723 }