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