formatting change
[tprouty/samba.git] / source / 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;
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   DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
347
348   *dirpath = 0;
349   *bad_path = False;
350   if(pst) {
351           ZERO_STRUCTP(pst);
352   }
353
354   if(saved_last_component)
355     *saved_last_component = 0;
356
357   /* 
358    * Convert to basic unix format - removing \ chars and cleaning it up.
359    */
360
361   unix_format(name);
362   unix_clean_name(name);
363
364   /* 
365    * Names must be relative to the root of the service - trim any leading /.
366    * also trim trailing /'s.
367    */
368
369   trim_string(name,"/","/");
370
371   /*
372    * If we trimmed down to a single '\0' character
373    * then we should use the "." directory to avoid
374    * searching the cache, but not if we are in a
375    * printing share.
376    */
377
378   if (!*name && (!conn -> printer)) {
379     name[0] = '.';
380     name[1] = '\0';
381   }
382
383   /*
384    * Ensure saved_last_component is valid even if file exists.
385    */
386
387   if(saved_last_component) {
388     end = strrchr(name, '/');
389     if(end)
390       pstrcpy(saved_last_component, end + 1);
391     else
392       pstrcpy(saved_last_component, name);
393   }
394
395   if (!case_sensitive && 
396       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
397     strnorm(name);
398
399   /* 
400    * Check if it's a printer file.
401    */
402   if (conn->printer) {
403     if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
404       char *s;
405       fstring name2;
406       slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
407
408       /* 
409        * Sanitise the name.
410        */
411
412       for (s=name2 ; *s ; s++)
413         if (!issafe(*s)) *s = '_';
414       pstrcpy(name,(char *)mktemp(name2));        
415     }      
416     return(True);
417   }
418
419   /*
420    * If we trimmed down to a single '\0' character
421    * then we will be using the "." directory.
422    * As we know this is valid we can return true here.
423    */
424
425   if(!*name)
426     return(True);
427
428   start = name;
429   while (strncmp(start,"./",2) == 0)
430     start += 2;
431
432   pstrcpy(orig_path, name);
433
434   if(stat_cache_lookup( name, dirpath, &start, &st)) {
435     if(pst)
436       *pst = st;
437     return True;
438   }
439
440   /* 
441    * stat the name - if it exists then we are all done!
442    */
443
444   if (dos_stat(name,&st) == 0) {
445     stat_cache_add(orig_path, name);
446     DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
447     if(pst)
448       *pst = st;
449     return(True);
450   }
451
452   saved_errno = errno;
453
454   DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
455         name, dirpath, start));
456
457   /* 
458    * A special case - if we don't have any mangling chars and are case
459    * sensitive then searching won't help.
460    */
461
462   if (case_sensitive && !is_mangled(name) && 
463       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
464     return(False);
465
466   if(strchr(start,'?') || strchr(start,'*'))
467     name_has_wildcard = True;
468
469   /* 
470    * is_mangled() was changed to look at an entire pathname, not 
471    * just a component. JRA.
472    */
473
474   if(is_mangled(start))
475     component_was_mangled = True;
476
477 #if 0
478   /* Keep Andrew's conservative code around, just in case. JRA. */
479   /* this is an extremely conservative test for mangled names. */
480   if (strchr(start,magic_char))
481     component_was_mangled = True;
482 #endif
483
484   /* 
485    * Now we need to recursively match the name against the real 
486    * directory structure.
487    */
488
489   /* 
490    * Match each part of the path name separately, trying the names
491    * as is first, then trying to scan the directory for matching names.
492    */
493
494   for (; start ; start = (end?end+1:(char *)NULL)) {
495       /* 
496        * Pinpoint the end of this section of the filename.
497        */
498       end = strchr(start, '/');
499
500       /* 
501        * Chop the name at this point.
502        */
503       if (end) 
504         *end = 0;
505
506       if(saved_last_component != 0)
507         pstrcpy(saved_last_component, end ? end + 1 : start);
508
509       /* 
510        * Check if the name exists up to this point.
511        */
512       if (dos_stat(name, &st) == 0) {
513         /*
514          * It exists. it must either be a directory or this must be
515          * the last part of the path for it to be OK.
516          */
517         if (end && !(st.st_mode & S_IFDIR)) {
518           /*
519            * An intermediate part of the name isn't a directory.
520             */
521           DEBUG(5,("Not a dir %s\n",start));
522           *end = '/';
523           return(False);
524         }
525
526       } else {
527         pstring rest;
528
529         *rest = 0;
530
531         /*
532          * Remember the rest of the pathname so it can be restored
533          * later.
534          */
535
536         if (end)
537           pstrcpy(rest,end+1);
538
539         /*
540          * Try to find this part of the path in the directory.
541          */
542
543         if (strchr(start,'?') || strchr(start,'*') ||
544             !scan_directory(dirpath, start, conn, end?True:False)) {
545           if (end) {
546             /*
547              * An intermediate part of the name can't be found.
548              */
549             DEBUG(5,("Intermediate not found %s\n",start));
550             *end = '/';
551
552             /* 
553              * We need to return the fact that the intermediate
554              * name resolution failed. This is used to return an
555              * error of ERRbadpath rather than ERRbadfile. Some
556              * Windows applications depend on the difference between
557              * these two errors.
558              */
559             *bad_path = True;
560             return(False);
561           }
562               
563           /* 
564            * Just the last part of the name doesn't exist.
565                * We may need to strupper() or strlower() it in case
566            * this conversion is being used for file creation 
567            * purposes. If the filename is of mixed case then 
568            * don't normalise it.
569            */
570
571           if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))           
572             strnorm(start);
573
574           /*
575            * check on the mangled stack to see if we can recover the 
576            * base of the filename.
577            */
578
579           if (is_mangled(start)) {
580             check_mangled_cache( start );
581           }
582
583           DEBUG(5,("New file %s\n",start));
584           return(True); 
585         }
586
587       /* 
588        * Restore the rest of the string.
589        */
590       if (end) {
591         pstrcpy(start+strlen(start)+1,rest);
592         end = start + strlen(start);
593       }
594     } /* end else */
595
596     /* 
597      * Add to the dirpath that we have resolved so far.
598      */
599     if (*dirpath)
600       pstrcat(dirpath,"/");
601
602     pstrcat(dirpath,start);
603
604     /*
605      * Don't cache a name with mangled or wildcard components
606      * as this can change the size.
607      */
608
609     if(!component_was_mangled && !name_has_wildcard)
610       stat_cache_add(orig_path, dirpath);
611
612     /* 
613      * Restore the / that we wiped out earlier.
614      */
615     if (end)
616       *end = '/';
617   }
618   
619   /*
620    * Don't cache a name with mangled or wildcard components
621    * as this can change the size.
622    */
623
624   if(!component_was_mangled && !name_has_wildcard)
625     stat_cache_add(orig_path, name);
626
627   /* 
628    * The name has been resolved.
629    */
630
631   DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
632   return(True);
633 }
634
635
636 /****************************************************************************
637 check a filename - possibly caling reducename
638
639 This is called by every routine before it allows an operation on a filename.
640 It does any final confirmation necessary to ensure that the filename is
641 a valid one for the user to access.
642 ****************************************************************************/
643 BOOL check_name(char *name,connection_struct *conn)
644 {
645   BOOL ret;
646
647   errno = 0;
648
649   if (IS_VETO_PATH(conn, name))  {
650           DEBUG(5,("file path name %s vetoed\n",name));
651           return(0);
652   }
653
654   ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
655
656   /* Check if we are allowing users to follow symlinks */
657   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
658      University of Geneva */
659
660 #ifdef S_ISLNK
661   if (!lp_symlinks(SNUM(conn)))
662     {
663       SMB_STRUCT_STAT statbuf;
664       if ( (dos_lstat(name,&statbuf) != -1) &&
665           (S_ISLNK(statbuf.st_mode)) )
666         {
667           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
668           ret=0; 
669         }
670     }
671 #endif
672
673   if (!ret)
674     DEBUG(5,("check_name on %s failed\n",name));
675
676   return(ret);
677 }
678
679
680 /****************************************************************************
681 scan a directory to find a filename, matching without case sensitivity
682
683 If the name looks like a mangled name then try via the mangling functions
684 ****************************************************************************/
685 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
686 {
687   void *cur_dir;
688   char *dname;
689   BOOL mangled;
690   pstring name2;
691
692   mangled = is_mangled(name);
693
694   /* handle null paths */
695   if (*path == 0)
696     path = ".";
697
698   if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
699     pstrcpy(name, dname);       
700     return(True);
701   }      
702
703   /*
704    * The incoming name can be mangled, and if we de-mangle it
705    * here it will not compare correctly against the filename (name2)
706    * read from the directory and then mangled by the name_map_mangle()
707    * call. We need to mangle both names or neither.
708    * (JRA).
709    */
710   if (mangled)
711     mangled = !check_mangled_cache( name );
712
713   /* open the directory */
714   if (!(cur_dir = OpenDir(conn, path, True))) 
715     {
716       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
717       return(False);
718     }
719
720   /* now scan for matching names */
721   while ((dname = ReadDirName(cur_dir))) 
722     {
723       if (*dname == '.' &&
724           (strequal(dname,".") || strequal(dname,"..")))
725         continue;
726
727       pstrcpy(name2,dname);
728       if (!name_map_mangle(name2,False,SNUM(conn))) continue;
729
730       if ((mangled && mangled_equal(name,name2))
731           || fname_equal(name, name2))
732         {
733           /* we've found the file, change it's name and return */
734           if (docache) DirCacheAdd(path,name,dname,SNUM(conn));
735           pstrcpy(name, dname);
736           CloseDir(cur_dir);
737           return(True);
738         }
739     }
740
741   CloseDir(cur_dir);
742   return(False);
743 }