Small bit of paranioa. Ensure that if the incoming name to
[samba.git] / source3 / smbd / filename.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    filename handling routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25 extern BOOL case_sensitive;
26 extern BOOL case_preserve;
27 extern BOOL short_case_preserve;
28 extern fstring remote_machine;
29 extern BOOL use_mangled_map;
30
31 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache);
32
33 /****************************************************************************
34  Check if two filenames are equal.
35  This needs to be careful about whether we are case sensitive.
36 ****************************************************************************/
37 static BOOL fname_equal(char *name1, char *name2)
38 {
39   int l1 = strlen(name1);
40   int l2 = strlen(name2);
41
42   /* handle filenames ending in a single dot */
43   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
44     {
45       BOOL ret;
46       name1[l1-1] = 0;
47       ret = fname_equal(name1,name2);
48       name1[l1-1] = '.';
49       return(ret);
50     }
51
52   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
53     {
54       BOOL ret;
55       name2[l2-1] = 0;
56       ret = fname_equal(name1,name2);
57       name2[l2-1] = '.';
58       return(ret);
59     }
60
61   /* now normal filename handling */
62   if (case_sensitive)
63     return(strcmp(name1,name2) == 0);
64
65   return(strequal(name1,name2));
66 }
67
68
69 /****************************************************************************
70  Mangle the 2nd name and check if it is then equal to the first name.
71 ****************************************************************************/
72 static BOOL mangled_equal(char *name1, char *name2)
73 {
74   pstring tmpname;
75
76   if (is_8_3(name2, True))
77     return(False);
78
79   pstrcpy(tmpname,name2);
80   mangle_name_83(tmpname);
81
82   return(strequal(name1,tmpname));
83 }
84
85 /****************************************************************************
86  Stat cache code used in unix_convert.
87 *****************************************************************************/
88
89 static int global_stat_cache_lookups;
90 static int global_stat_cache_misses;
91 static int global_stat_cache_hits;
92
93 /****************************************************************************
94  Stat cache statistics code.
95 *****************************************************************************/
96
97 void print_stat_cache_statistics(void)
98 {
99   double eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups;
100
101   DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \
102 stat cache was %f%% effective.\n", global_stat_cache_lookups,
103        global_stat_cache_hits, global_stat_cache_misses, eff ));
104 }
105
106 typedef struct {
107   ubi_dlNode link;
108   int name_len;
109   pstring orig_name;
110   pstring translated_name;
111 } stat_cache_entry;
112
113 #define MAX_STAT_CACHE_SIZE 50
114
115 static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0};
116
117 /****************************************************************************
118  Compare a pathname to a name in the stat cache - of a given length.
119  Note - this code always checks that the next character in the pathname
120  is either a '/' character, or a '\0' character - to ensure we only
121  match *full* pathname components. Note we don't need to handle case
122  here, if we're case insensitive the stat cache orig names are all upper
123  case.
124 *****************************************************************************/
125
126 static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len)
127 {
128   BOOL matched = (memcmp( stat_name, orig_name, len) == 0);
129   if(orig_name[len] != '/' && orig_name[len] != '\0')
130     return False;
131
132   return matched;
133 }
134
135 /****************************************************************************
136  Add an entry into the stat cache.
137 *****************************************************************************/
138
139 static void stat_cache_add( char *full_orig_name, char *orig_translated_path)
140 {
141   stat_cache_entry *scp;
142   pstring orig_name;
143   pstring translated_path;
144   int namelen;
145
146   if (!lp_stat_cache()) return;
147
148   namelen = strlen(orig_translated_path);
149
150   /*
151    * Don't cache trivial valid directory entries.
152    */
153   if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) ||
154      (strcmp(full_orig_name, "..") == 0))
155     return;
156
157   /*
158    * If we are in case insentive mode, we need to
159    * store names that need no translation - else, it
160    * would be a waste.
161    */
162
163   if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0))
164     return;
165
166   /*
167    * Remove any trailing '/' characters from the
168    * translated path.
169    */
170
171   pstrcpy(translated_path, orig_translated_path);
172   if(translated_path[namelen-1] == '/') {
173     translated_path[namelen-1] = '\0';
174     namelen--;
175   }
176
177   /*
178    * We will only replace namelen characters 
179    * of full_orig_name.
180    * StrnCpy always null terminates.
181    */
182
183   StrnCpy(orig_name, full_orig_name, namelen);
184   if(!case_sensitive)
185     strupper( orig_name );
186
187   /*
188    * Check this name doesn't exist in the cache before we 
189    * add it.
190    */
191
192   for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; 
193                         scp = (stat_cache_entry *)ubi_dlNext( scp )) {
194     if((strcmp( scp->orig_name, orig_name) == 0) &&
195        (strcmp( scp->translated_name, translated_path) == 0)) {
196       /*
197        * Name does exist - promote it.
198        */
199       if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) {
200         ubi_dlRemThis( &stat_cache, scp);
201         ubi_dlAddHead( &stat_cache, scp);
202       }
203       return;
204     }
205   }
206
207   if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) {
208     DEBUG(0,("stat_cache_add: Out of memory !\n"));
209     return;
210   }
211
212   pstrcpy(scp->orig_name, orig_name);
213   pstrcpy(scp->translated_name, translated_path);
214   scp->name_len = namelen;
215
216   ubi_dlAddHead( &stat_cache, scp);
217
218   DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name ));
219
220   if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) {
221     scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache );
222     free((char *)scp);
223     return;
224   }
225 }
226
227 /****************************************************************************
228  Look through the stat cache for an entry - promote it to the top if found.
229  Return True if we translated (and did a scuccessful stat on) the entire name.
230 *****************************************************************************/
231
232 static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst)
233 {
234   stat_cache_entry *scp;
235   stat_cache_entry *longest_hit = NULL;
236   pstring chk_name;
237   int namelen;
238
239   if (!lp_stat_cache()) return False;
240  
241   namelen = strlen(name);
242
243   *start = name;
244   global_stat_cache_lookups++;
245
246   /*
247    * Don't lookup trivial valid directory entries.
248    */
249   if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) {
250     global_stat_cache_misses++;
251     return False;
252   }
253
254   pstrcpy(chk_name, name);
255   if(!case_sensitive)
256     strupper( chk_name );
257
258   for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; 
259                         scp = (stat_cache_entry *)ubi_dlNext( scp )) {
260     if(scp->name_len <= namelen) {
261       if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) {
262         if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len))
263           longest_hit = scp;
264       }
265     }
266   }
267
268   if(longest_hit == NULL) {
269     DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name));
270     global_stat_cache_misses++;
271     return False;
272   }
273
274   global_stat_cache_hits++;
275
276   DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n",
277         name, longest_hit->orig_name, longest_hit->translated_name ));
278
279   /*
280    * longest_hit is the longest match we got in the list.
281    * Check it exists - if so, overwrite the original name
282    * and then promote it to the top.
283    */
284
285   if(dos_stat( longest_hit->translated_name, pst) != 0) {
286     /*
287      * Discard this entry.
288      */
289     ubi_dlRemThis( &stat_cache, longest_hit);
290     free((char *)longest_hit);
291     return False;
292   }
293
294   memcpy(name, longest_hit->translated_name, longest_hit->name_len);
295   if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) {
296     ubi_dlRemThis( &stat_cache, longest_hit);
297     ubi_dlAddHead( &stat_cache, longest_hit);
298   }
299
300   *start = &name[longest_hit->name_len];
301   if(**start == '/')
302     ++*start;
303
304   StrnCpy( dirpath, longest_hit->translated_name, name - (*start));
305
306   return (namelen == longest_hit->name_len);
307 }
308
309 /****************************************************************************
310 This routine is called to convert names from the dos namespace to unix
311 namespace. It needs to handle any case conversions, mangling, format
312 changes etc.
313
314 We assume that we have already done a chdir() to the right "root" directory
315 for this service.
316
317 The function will return False if some part of the name except for the last
318 part cannot be resolved
319
320 If the saved_last_component != 0, then the unmodified last component
321 of the pathname is returned there. This is used in an exceptional
322 case in reply_mv (so far). If saved_last_component == 0 then nothing
323 is returned there.
324
325 The bad_path arg is set to True if the filename walk failed. This is
326 used to pick the correct error code to return between ENOENT and ENOTDIR
327 as Windows applications depend on ERRbadpath being returned if a component
328 of a pathname does not exist.
329 ****************************************************************************/
330
331 BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, 
332                   BOOL *bad_path, SMB_STRUCT_STAT *pst)
333 {
334   SMB_STRUCT_STAT st;
335   char *start, *end, *orig_start;
336   pstring dirpath;
337   pstring orig_path;
338   int saved_errno;
339   BOOL component_was_mangled = False;
340   BOOL name_has_wildcard = False;
341 #if 0
342   /* Andrew's conservative code... JRA. */
343   extern char magic_char;
344 #endif
345
346   *dirpath = 0;
347   *bad_path = False;
348   if(pst) {
349           ZERO_STRUCTP(pst);
350   }
351
352   if(saved_last_component)
353     *saved_last_component = 0;
354
355   /* 
356    * Convert to basic unix format - removing \ chars and cleaning it up.
357    */
358
359   unix_format(name);
360   unix_clean_name(name);
361
362   /* 
363    * Names must be relative to the root of the service - trim any leading /.
364    * also trim trailing /'s.
365    */
366
367   trim_string(name,"/","/");
368
369   /*
370    * If we trimmed down to a single '\0' character
371    * then we should use the "." directory to avoid
372    * searching the cache.
373    */
374
375   if(!*name) {
376     name[0] = '.';
377     name[1] = '\0';
378   }
379
380   /*
381    * Ensure saved_last_component is valid even if file exists.
382    */
383
384   if(saved_last_component) {
385     end = strrchr(name, '/');
386     if(end)
387       pstrcpy(saved_last_component, end + 1);
388     else
389       pstrcpy(saved_last_component, name);
390   }
391
392   if (!case_sensitive && 
393       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
394     strnorm(name);
395
396   /* 
397    * Check if it's a printer file.
398    */
399   if (conn->printer) {
400     if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
401       char *s;
402       fstring name2;
403       slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
404
405       /* 
406        * Sanitise the name.
407        */
408
409       for (s=name2 ; *s ; s++)
410         if (!issafe(*s)) *s = '_';
411           pstrcpy(name,(char *)mktemp(name2));    
412     }      
413     return(True);
414   }
415
416   start = name;
417   while (strncmp(start,"./",2) == 0)
418     start += 2;
419
420   pstrcpy(orig_path, name);
421
422   if(stat_cache_lookup( name, dirpath, &start, &st)) {
423     if(pst)
424       *pst = st;
425     return True;
426   }
427
428   /* 
429    * stat the name - if it exists then we are all done!
430    */
431
432   if (dos_stat(name,&st) == 0) {
433     stat_cache_add(orig_path, name);
434     DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
435     if(pst)
436       *pst = st;
437     return(True);
438   }
439
440   saved_errno = errno;
441
442   DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
443         name, dirpath, start));
444
445   /* 
446    * A special case - if we don't have any mangling chars and are case
447    * sensitive then searching won't help.
448    */
449
450   if (case_sensitive && !is_mangled(name) && 
451       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
452     return(False);
453
454   if(strchr(start,'?') || strchr(start,'*'))
455     name_has_wildcard = True;
456
457   /* 
458    * is_mangled() was changed to look at an entire pathname, not 
459    * just a component. JRA.
460    */
461
462   if(is_mangled(start))
463     component_was_mangled = True;
464
465 #if 0
466   /* Keep Andrew's conservative code around, just in case. JRA. */
467   /* this is an extremely conservative test for mangled names. */
468   if (strchr(start,magic_char))
469     component_was_mangled = True;
470 #endif
471
472   /* 
473    * Now we need to recursively match the name against the real 
474    * directory structure.
475    */
476
477   /* 
478    * Match each part of the path name separately, trying the names
479    * as is first, then trying to scan the directory for matching names.
480    */
481
482   for (orig_start = start; start ; start = (end?end+1:(char *)NULL)) {
483       /* 
484        * Pinpoint the end of this section of the filename.
485        */
486       end = strchr(start, '/');
487
488       /* 
489        * Chop the name at this point.
490        */
491       if (end) 
492         *end = 0;
493
494       if(saved_last_component != 0)
495         pstrcpy(saved_last_component, end ? end + 1 : start);
496
497       /* 
498        * Check if the name exists up to this point.
499        */
500       if (dos_stat(name, &st) == 0) {
501         /*
502          * It exists. it must either be a directory or this must be
503          * the last part of the path for it to be OK.
504          */
505         if (end && !(st.st_mode & S_IFDIR)) {
506           /*
507            * An intermediate part of the name isn't a directory.
508             */
509           DEBUG(5,("Not a dir %s\n",start));
510           *end = '/';
511           return(False);
512         }
513
514       } else {
515         pstring rest;
516
517         *rest = 0;
518
519         /*
520          * Remember the rest of the pathname so it can be restored
521          * later.
522          */
523
524         if (end)
525           pstrcpy(rest,end+1);
526
527         /*
528          * Try to find this part of the path in the directory.
529          */
530
531         if (strchr(start,'?') || strchr(start,'*') ||
532             !scan_directory(dirpath, start, conn, end?True:False)) {
533           if (end) {
534             /*
535              * An intermediate part of the name can't be found.
536              */
537             DEBUG(5,("Intermediate not found %s\n",start));
538             *end = '/';
539
540             /* 
541              * We need to return the fact that the intermediate
542              * name resolution failed. This is used to return an
543              * error of ERRbadpath rather than ERRbadfile. Some
544              * Windows applications depend on the difference between
545              * these two errors.
546              */
547             *bad_path = True;
548             return(False);
549           }
550               
551           /* 
552            * Just the last part of the name doesn't exist.
553                * We may need to strupper() or strlower() it in case
554            * this conversion is being used for file creation 
555            * purposes. If the filename is of mixed case then 
556            * don't normalise it.
557            */
558
559           if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))           
560             strnorm(start);
561
562           /*
563            * check on the mangled stack to see if we can recover the 
564            * base of the filename.
565            */
566
567           if (is_mangled(start)) {
568             check_mangled_cache( start );
569           }
570
571           DEBUG(5,("New file %s\n",start));
572           return(True); 
573         }
574
575       /* 
576        * Restore the rest of the string.
577        */
578       if (end) {
579         pstrcpy(start+strlen(start)+1,rest);
580         end = start + strlen(start);
581       }
582     } /* end else */
583
584     /* 
585      * Add to the dirpath that we have resolved so far.
586      */
587     if (*dirpath)
588       pstrcat(dirpath,"/");
589
590     pstrcat(dirpath,start);
591
592     /*
593      * Don't cache a name with mangled or wildcard components
594      * as this can change the size.
595      */
596
597     if(!component_was_mangled && !name_has_wildcard)
598       stat_cache_add(orig_path, dirpath);
599
600     /* 
601      * Restore the / that we wiped out earlier.
602      */
603     if (end)
604       *end = '/';
605   }
606   
607   /*
608    * Don't cache a name with mangled or wildcard components
609    * as this can change the size.
610    */
611
612   if(!component_was_mangled && !name_has_wildcard)
613     stat_cache_add(orig_path, name);
614
615   /* 
616    * The name has been resolved.
617    */
618
619   DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
620   return(True);
621 }
622
623
624 /****************************************************************************
625 check a filename - possibly caling reducename
626
627 This is called by every routine before it allows an operation on a filename.
628 It does any final confirmation necessary to ensure that the filename is
629 a valid one for the user to access.
630 ****************************************************************************/
631 BOOL check_name(char *name,connection_struct *conn)
632 {
633   BOOL ret;
634
635   errno = 0;
636
637   if (IS_VETO_PATH(conn, name))  {
638           DEBUG(5,("file path name %s vetoed\n",name));
639           return(0);
640   }
641
642   ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
643
644   /* Check if we are allowing users to follow symlinks */
645   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
646      University of Geneva */
647
648 #ifdef S_ISLNK
649   if (!lp_symlinks(SNUM(conn)))
650     {
651       SMB_STRUCT_STAT statbuf;
652       if ( (dos_lstat(name,&statbuf) != -1) &&
653           (S_ISLNK(statbuf.st_mode)) )
654         {
655           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
656           ret=0; 
657         }
658     }
659 #endif
660
661   if (!ret)
662     DEBUG(5,("check_name on %s failed\n",name));
663
664   return(ret);
665 }
666
667
668 /****************************************************************************
669 scan a directory to find a filename, matching without case sensitivity
670
671 If the name looks like a mangled name then try via the mangling functions
672 ****************************************************************************/
673 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
674 {
675   void *cur_dir;
676   char *dname;
677   BOOL mangled;
678   pstring name2;
679
680   mangled = is_mangled(name);
681
682   /* handle null paths */
683   if (*path == 0)
684     path = ".";
685
686   if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
687     pstrcpy(name, dname);       
688     return(True);
689   }      
690
691   /*
692    * The incoming name can be mangled, and if we de-mangle it
693    * here it will not compare correctly against the filename (name2)
694    * read from the directory and then mangled by the name_map_mangle()
695    * call. We need to mangle both names or neither.
696    * (JRA).
697    */
698   if (mangled)
699     mangled = !check_mangled_cache( name );
700
701   /* open the directory */
702   if (!(cur_dir = OpenDir(conn, path, True))) 
703     {
704       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
705       return(False);
706     }
707
708   /* now scan for matching names */
709   while ((dname = ReadDirName(cur_dir))) 
710     {
711       if (*dname == '.' &&
712           (strequal(dname,".") || strequal(dname,"..")))
713         continue;
714
715       pstrcpy(name2,dname);
716       if (!name_map_mangle(name2,False,SNUM(conn))) continue;
717
718       if ((mangled && mangled_equal(name,name2))
719           || fname_equal(name, name2))
720         {
721           /* we've found the file, change it's name and return */
722           if (docache) DirCacheAdd(path,name,dname,SNUM(conn));
723           pstrcpy(name, dname);
724           CloseDir(cur_dir);
725           return(True);
726         }
727     }
728
729   CloseDir(cur_dir);
730   return(False);
731 }