r24549: Fix unix_convert to return the already converted part
[ira/wip.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-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                 return result;
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                 SAFE_FREE(name);
226                 return NT_STATUS_NO_MEMORY;
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                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
241                                 goto fail;
242                         } else if (p[2] == '\0') {
243                                 /* Error code at the end of a pathname. */
244                                 result = NT_STATUS_OBJECT_NAME_INVALID;
245                                 goto fail;
246                         }
247                 }
248                 stat_cache_add(orig_path, name, conn->case_sensitive);
249                 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
250                 *pst = st;
251                 goto done;
252         }
253
254         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
255
256         /*
257          * A special case - if we don't have any mangling chars and are case
258          * sensitive then searching won't help.
259          */
260
261         if (conn->case_sensitive &&
262                         !mangle_is_mangled(name, conn->params) &&
263                         !*lp_mangled_map(conn->params)) {
264                 goto done;
265         }
266
267         /*
268          * is_mangled() was changed to look at an entire pathname, not
269          * just a component. JRA.
270          */
271
272         if (mangle_is_mangled(start, conn->params)) {
273                 component_was_mangled = True;
274         }
275
276         /*
277          * Now we need to recursively match the name against the real
278          * directory structure.
279          */
280
281         /*
282          * Match each part of the path name separately, trying the names
283          * as is first, then trying to scan the directory for matching names.
284          */
285
286         for (; start ; start = (end?end+1:(char *)NULL)) {
287                 /*
288                  * Pinpoint the end of this section of the filename.
289                  */
290                 end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */
291
292                 /*
293                  * Chop the name at this point.
294                  */
295                 if (end) {
296                         *end = 0;
297                 }
298
299                 if (saved_last_component != 0) {
300                         pstrcpy(saved_last_component, end ? end + 1 : start);
301                 }
302
303                 /* The name cannot have a component of "." */
304
305                 if (ISDOT(start)) {
306                         if (!end)  {
307                                 /* Error code at the end of a pathname. */
308                                 result = NT_STATUS_OBJECT_NAME_INVALID;
309                         } else {
310                                 result = determine_path_error(end+1,
311                                                 allow_wcard_last_component);
312                         }
313                         goto fail;
314                 }
315
316                 /* The name cannot have a wildcard if it's not
317                    the last component. */
318
319                 name_has_wildcard = ms_has_wild(start);
320
321                 /* Wildcard not valid anywhere. */
322                 if (name_has_wildcard && !allow_wcard_last_component) {
323                         result = NT_STATUS_OBJECT_NAME_INVALID;
324                         goto fail;
325                 }
326
327                 /* Wildcards never valid within a pathname. */
328                 if (name_has_wildcard && end) {
329                         result = NT_STATUS_OBJECT_NAME_INVALID;
330                         goto fail;
331                 }
332
333                 /*
334                  * Check if the name exists up to this point.
335                  */
336
337                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
338                         /*
339                          * It exists. it must either be a directory or this must be
340                          * the last part of the path for it to be OK.
341                          */
342                         if (end && !(st.st_mode & S_IFDIR)) {
343                                 /*
344                                  * An intermediate part of the name isn't a directory.
345                                  */
346                                 DEBUG(5,("Not a dir %s\n",start));
347                                 *end = '/';
348                                 /*
349                                  * We need to return the fact that the intermediate
350                                  * name resolution failed. This is used to return an
351                                  * error of ERRbadpath rather than ERRbadfile. Some
352                                  * Windows applications depend on the difference between
353                                  * these two errors.
354                                  */
355                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
356                                 goto fail;
357                         }
358
359                         if (!end) {
360                                 /*
361                                  * We just scanned for, and found the end of the path.
362                                  * We must return the valid stat struct.
363                                  * JRA.
364                                  */
365
366                                 *pst = st;
367                         }
368
369                 } else {
370                         char *found_name = NULL;
371
372                         /* Stat failed - ensure we don't use it. */
373                         SET_STAT_INVALID(st);
374
375                         /* Reset errno so we can detect directory open errors. */
376                         errno = 0;
377
378                         /*
379                          * Try to find this part of the path in the directory.
380                          */
381
382                         if (name_has_wildcard || 
383                             !scan_directory(conn, dirpath, start, &found_name)) {
384                                 char *unmangled;
385
386                                 if (end) {
387                                         /*
388                                          * An intermediate part of the name can't be found.
389                                          */
390                                         DEBUG(5,("Intermediate not found %s\n",start));
391                                         *end = '/';
392
393                                         /*
394                                          * We need to return the fact that the intermediate
395                                          * name resolution failed. This is used to return an
396                                          * error of ERRbadpath rather than ERRbadfile. Some
397                                          * Windows applications depend on the difference between
398                                          * these two errors.
399                                          */
400
401                                         /*
402                                          * ENOENT, ENOTDIR and ELOOP all map
403                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
404                                          * in the filename walk.
405                                          */
406
407                                         if (errno == ENOENT ||
408                                                         errno == ENOTDIR ||
409                                                         errno == ELOOP) {
410                                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
411                                         }
412                                         else {
413                                                 result = map_nt_error_from_unix(errno);
414                                         }
415                                         goto fail;
416                                 }
417
418                                 /* ENOENT is the only valid error here. */
419                                 if (errno != ENOENT) {
420                                         /*
421                                          * ENOTDIR and ELOOP both map to
422                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
423                                          * in the filename walk.
424                                          */
425                                         if (errno == ENOTDIR ||
426                                                         errno == ELOOP) {
427                                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
428                                         }
429                                         else {
430                                                 result = map_nt_error_from_unix(errno);
431                                         }
432                                         goto fail;
433                                 }
434
435                                 /*
436                                  * Just the last part of the name doesn't exist.
437                                  * We need to strupper() or strlower() it as
438                                  * this conversion may be used for file creation 
439                                  * purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>.
440                                  */
441                                 if (!conn->case_preserve ||
442                                     (mangle_is_8_3(start, False, conn->params) &&
443                                                  !conn->short_case_preserve)) {
444                                         strnorm(start, lp_defaultcase(SNUM(conn)));
445                                 }
446
447                                 /*
448                                  * check on the mangled stack to see if we can recover the 
449                                  * base of the filename.
450                                  */
451
452                                 if (mangle_is_mangled(start, conn->params)
453                                     && mangle_check_cache_alloc(start, &unmangled,
454                                                                 conn->params)) {
455                                         char *tmp;
456                                         size_t start_ofs = start - name;
457
458                                         if (*dirpath != '\0') {
459                                                 asprintf(&tmp, "%s/%s", dirpath,
460                                                          unmangled);
461                                                 SAFE_FREE(unmangled);
462                                         }
463                                         else {
464                                                 tmp = unmangled;
465                                         }
466                                         if (tmp == NULL) {
467                                                 DEBUG(0, ("malloc failed\n"));
468                                                 result = NT_STATUS_NO_MEMORY;
469                                         }
470                                         SAFE_FREE(name);
471                                         name = tmp;
472                                         start = name + start_ofs;
473                                         end = start + strlen(start);
474                                 }
475
476                                 DEBUG(5,("New file %s\n",start));
477                                 goto done;
478                         }
479
480
481                         /*
482                          * Restore the rest of the string. If the string was mangled the size
483                          * may have changed.
484                          */
485                         if (end) {
486                                 char *tmp;
487                                 size_t start_ofs = start - name;
488
489                                 if (*dirpath != '\0') {
490                                         asprintf(&tmp, "%s/%s/%s", dirpath,
491                                                  found_name, end+1);
492                                 }
493                                 else {
494                                         asprintf(&tmp, "%s/%s", found_name,
495                                                  end+1);
496                                 }
497                                 if (tmp == NULL) {
498                                         DEBUG(0, ("asprintf failed\n"));
499                                         result = NT_STATUS_NO_MEMORY;
500                                 }
501                                 SAFE_FREE(name);
502                                 name = tmp;
503                                 start = name + start_ofs;
504                                 end = start + strlen(found_name);
505                                 *end = '\0';
506                         } else {
507                                 char *tmp;
508                                 size_t start_ofs = start - name;
509
510                                 if (*dirpath != '\0') {
511                                         asprintf(&tmp, "%s/%s", dirpath,
512                                                  found_name);
513                                 }
514                                 else {
515                                         tmp = SMB_STRDUP(found_name);
516                                 }
517                                 if (tmp == NULL) {
518                                         DEBUG(0, ("malloc failed\n"));
519                                         result = NT_STATUS_NO_MEMORY;
520                                         goto fail;
521                                 }
522                                 SAFE_FREE(name);
523                                 name = tmp;
524                                 start = name + start_ofs;
525
526                                 /*
527                                  * We just scanned for, and found the end of the path.
528                                  * We must return a valid stat struct if it exists.
529                                  * JRA.
530                                  */
531
532                                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
533                                         *pst = st;
534                                 } else {
535                                         SET_STAT_INVALID(st);
536                                 }
537                         }
538
539                         SAFE_FREE(found_name);
540                 } /* end else */
541
542 #ifdef DEVELOPER
543                 if (VALID_STAT(st) &&
544                     get_delete_on_close_flag(vfs_file_id_from_sbuf(conn, &st))) {
545                         result = NT_STATUS_DELETE_PENDING;
546                         goto fail;
547                 }
548 #endif
549
550                 /* 
551                  * Add to the dirpath that we have resolved so far.
552                  */
553
554                 if (*dirpath != '\0') {
555                         char *tmp;
556
557                         if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) {
558                                 DEBUG(0, ("asprintf failed\n"));
559                                 return NT_STATUS_NO_MEMORY;
560                         }
561                         SAFE_FREE(dirpath);
562                         dirpath = tmp;
563                 }
564                 else {
565                         SAFE_FREE(dirpath);
566                         if (!(dirpath = SMB_STRDUP(start))) {
567                                 DEBUG(0, ("strdup failed\n"));
568                                 return NT_STATUS_NO_MEMORY;
569                         }
570                 }
571
572                 /*
573                  * Don't cache a name with mangled or wildcard components
574                  * as this can change the size.
575                  */
576
577                 if(!component_was_mangled && !name_has_wildcard) {
578                         stat_cache_add(orig_path, dirpath, conn->case_sensitive);
579                 }
580
581                 /*
582                  * Restore the / that we wiped out earlier.
583                  */
584                 if (end) {
585                         *end = '/';
586                 }
587         }
588
589         /*
590          * Don't cache a name with mangled or wildcard components
591          * as this can change the size.
592          */
593
594         if(!component_was_mangled && !name_has_wildcard) {
595                 stat_cache_add(orig_path, name, conn->case_sensitive);
596         }
597
598         /*
599          * The name has been resolved.
600          */
601
602         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
603
604  done:
605         pstrcpy(orig_path, name);
606         SAFE_FREE(name);
607         SAFE_FREE(dirpath);
608         return NT_STATUS_OK;
609  fail:
610         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
611         pstrcpy(orig_path, dirpath);
612         pstrcat(orig_path, "/");
613         pstrcat(orig_path, start);
614         SAFE_FREE(name);
615         SAFE_FREE(dirpath);
616         return result;
617 }
618
619 /****************************************************************************
620  Check a filename - possibly calling check_reduced_name.
621  This is called by every routine before it allows an operation on a filename.
622  It does any final confirmation necessary to ensure that the filename is
623  a valid one for the user to access.
624 ****************************************************************************/
625
626 NTSTATUS check_name(connection_struct *conn, const pstring name)
627 {
628         if (IS_VETO_PATH(conn, name))  {
629                 /* Is it not dot or dot dot. */
630                 if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
631                         DEBUG(5,("check_name: file path name %s vetoed\n",name));
632                         return map_nt_error_from_unix(ENOENT);
633                 }
634         }
635
636         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
637                 NTSTATUS status = check_reduced_name(conn,name);
638                 if (!NT_STATUS_IS_OK(status)) {
639                         DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status)));
640                         return status;
641                 }
642         }
643
644         return NT_STATUS_OK;
645 }
646
647 /****************************************************************************
648  Check if two filenames are equal.
649  This needs to be careful about whether we are case sensitive.
650 ****************************************************************************/
651
652 static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive)
653 {
654         /* Normal filename handling */
655         if (case_sensitive)
656                 return(strcmp(name1,name2) == 0);
657
658         return(strequal(name1,name2));
659 }
660
661 /****************************************************************************
662  Scan a directory to find a filename, matching without case sensitivity.
663  If the name looks like a mangled name then try via the mangling functions
664 ****************************************************************************/
665
666 static BOOL scan_directory(connection_struct *conn, const char *path,
667                            char *name, char **found_name)
668 {
669         struct smb_Dir *cur_dir;
670         const char *dname;
671         BOOL mangled;
672         char *unmangled_name = NULL;
673         long curpos;
674
675         mangled = mangle_is_mangled(name, conn->params);
676
677         /* handle null paths */
678         if ((path == NULL) || (*path == 0))
679                 path = ".";
680
681         /*
682          * The incoming name can be mangled, and if we de-mangle it
683          * here it will not compare correctly against the filename (name2)
684          * read from the directory and then mangled by the mangle_map()
685          * call. We need to mangle both names or neither.
686          * (JRA).
687          *
688          * Fix for bug found by Dina Fine. If in case sensitive mode then
689          * the mangle cache is no good (3 letter extension could be wrong
690          * case - so don't demangle in this case - leave as mangled and
691          * allow the mangling of the directory entry read (which is done
692          * case insensitively) to match instead. This will lead to more
693          * false positive matches but we fail completely without it. JRA.
694          */
695
696         if (mangled && !conn->case_sensitive) {
697                 mangled = !mangle_check_cache_alloc(name, &unmangled_name,
698                                                     conn->params);
699                 name = unmangled_name;
700         }
701
702         /* open the directory */
703         if (!(cur_dir = OpenDir(conn, path, NULL, 0))) {
704                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
705                 SAFE_FREE(unmangled_name);
706                 return(False);
707         }
708
709         /* now scan for matching names */
710         curpos = 0;
711         while ((dname = ReadDirName(cur_dir, &curpos))) {
712
713                 /* Is it dot or dot dot. */
714                 if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) {
715                         continue;
716                 }
717
718                 /*
719                  * At this point dname is the unmangled name.
720                  * name is either mangled or not, depending on the state of the "mangled"
721                  * variable. JRA.
722                  */
723
724                 /*
725                  * Check mangled name against mangled name, or unmangled name
726                  * against unmangled name.
727                  */
728
729                 if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) {
730                         /* we've found the file, change it's name and return */
731                         *found_name = SMB_STRDUP(dname);
732                         SAFE_FREE(unmangled_name);
733                         CloseDir(cur_dir);
734                         return(True);
735                 }
736         }
737
738         SAFE_FREE(unmangled_name);
739         CloseDir(cur_dir);
740         errno = ENOENT;
741         return(False);
742 }