r656: Make widelinks use realpath(). Tidy up cases where we need to become a service.
[samba.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    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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(const char *path, char *name,size_t maxlength,
30                            connection_struct *conn,BOOL docache);
31
32 /****************************************************************************
33  Check if two filenames are equal.
34  This needs to be careful about whether we are case sensitive.
35 ****************************************************************************/
36
37 static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitive)
38 {
39         /* Normal filename handling */
40         if (case_sensitive)
41                 return(strcmp(name1,name2) == 0);
42
43         return(strequal(name1,name2));
44 }
45
46 /****************************************************************************
47  Mangle the 2nd name and check if it is then equal to the first name.
48 ****************************************************************************/
49
50 static BOOL mangled_equal(const char *name1, const char *name2, int snum)
51 {
52         pstring tmpname;
53         
54         pstrcpy(tmpname, name2);
55         mangle_map(tmpname, True, False, snum);
56         return strequal(name1, tmpname);
57 }
58
59 /****************************************************************************
60 This routine is called to convert names from the dos namespace to unix
61 namespace. It needs to handle any case conversions, mangling, format
62 changes etc.
63
64 We assume that we have already done a chdir() to the right "root" directory
65 for this service.
66
67 The function will return False if some part of the name except for the last
68 part cannot be resolved
69
70 If the saved_last_component != 0, then the unmodified last component
71 of the pathname is returned there. This is used in an exceptional
72 case in reply_mv (so far). If saved_last_component == 0 then nothing
73 is returned there.
74
75 The bad_path arg is set to True if the filename walk failed. This is
76 used to pick the correct error code to return between ENOENT and ENOTDIR
77 as Windows applications depend on ERRbadpath being returned if a component
78 of a pathname does not exist.
79
80 On exit from unix_convert, if *pst was not null, then the file stat
81 struct will be returned if the file exists and was found, if not this
82 stat struct will be filled with zeros (and this can be detected by checking
83 for nlinks = 0, which can never be true for any file).
84 ****************************************************************************/
85
86 BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, 
87                   BOOL *bad_path, SMB_STRUCT_STAT *pst)
88 {
89         SMB_STRUCT_STAT st;
90         char *start, *end;
91         pstring dirpath;
92         pstring orig_path;
93         BOOL component_was_mangled = False;
94         BOOL name_has_wildcard = False;
95
96         ZERO_STRUCTP(pst);
97
98         *dirpath = 0;
99         *bad_path = False;
100         if(saved_last_component)
101                 *saved_last_component = 0;
102
103         if (conn->printer) {
104                 /* we don't ever use the filenames on a printer share as a
105                         filename - so don't convert them */
106                 return True;
107         }
108
109         DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
110
111         /* 
112          * Conversion to basic unix format is already done in check_path_syntax().
113          */
114
115         /* 
116          * Names must be relative to the root of the service - any leading /.
117          * and trailing /'s should have been trimmed by check_path_syntax().
118          */
119
120 #ifdef DEVELOPER
121         SMB_ASSERT(*name != '/');
122 #endif
123
124         /*
125          * If we trimmed down to a single '\0' character
126          * then we should use the "." directory to avoid
127          * searching the cache, but not if we are in a
128          * printing share.
129          * As we know this is valid we can return true here.
130          */
131
132         if (!*name) {
133                 name[0] = '.';
134                 name[1] = '\0';
135                 return(True);
136         }
137
138         /*
139          * Ensure saved_last_component is valid even if file exists.
140          */
141
142         if(saved_last_component) {
143                 end = strrchr_m(name, '/');
144                 if(end)
145                         pstrcpy(saved_last_component, end + 1);
146                 else
147                         pstrcpy(saved_last_component, name);
148         }
149
150 #if 1
151         if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve))
152 #else
153         if (!conn->case_sensitive && (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)))
154 #endif
155                 strnorm(name, lp_defaultcase(SNUM(conn)));
156
157         start = name;
158         pstrcpy(orig_path, name);
159
160         if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) {
161                 *pst = st;
162                 return True;
163         }
164
165         /* 
166          * stat the name - if it exists then we are all done!
167          */
168
169         if (SMB_VFS_STAT(conn,name,&st) == 0) {
170                 stat_cache_add(orig_path, name, conn->case_sensitive);
171                 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
172                 *pst = st;
173                 return(True);
174         }
175
176         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
177
178         /* 
179          * A special case - if we don't have any mangling chars and are case
180          * sensitive then searching won't help.
181          */
182
183         if (conn->case_sensitive && !mangle_is_mangled(name) && !*lp_mangled_map(SNUM(conn)))
184                 return(False);
185
186         name_has_wildcard = ms_has_wild(start);
187
188         /* 
189          * is_mangled() was changed to look at an entire pathname, not 
190          * just a component. JRA.
191          */
192
193         if (mangle_is_mangled(start))
194                 component_was_mangled = True;
195
196         /* 
197          * Now we need to recursively match the name against the real 
198          * directory structure.
199          */
200
201         /* 
202          * Match each part of the path name separately, trying the names
203          * as is first, then trying to scan the directory for matching names.
204          */
205
206         for (; start ; start = (end?end+1:(char *)NULL)) {
207                 /* 
208                  * Pinpoint the end of this section of the filename.
209                  */
210                 end = strchr_m(start, '/');
211
212                 /* 
213                  * Chop the name at this point.
214                  */
215                 if (end) 
216                         *end = 0;
217
218                 if(saved_last_component != 0)
219                         pstrcpy(saved_last_component, end ? end + 1 : start);
220
221                 /* 
222                  * Check if the name exists up to this point.
223                  */
224
225                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
226                         /*
227                          * It exists. it must either be a directory or this must be
228                          * the last part of the path for it to be OK.
229                          */
230                         if (end && !(st.st_mode & S_IFDIR)) {
231                                 /*
232                                  * An intermediate part of the name isn't a directory.
233                                  */
234                                 DEBUG(5,("Not a dir %s\n",start));
235                                 *end = '/';
236                                 return(False);
237                         }
238
239                         if (!end) {
240                                 /*
241                                  * We just scanned for, and found the end of the path.
242                                  * We must return the valid stat struct.
243                                  * JRA.
244                                  */
245
246                                 *pst = st;
247                         }
248
249                 } else {
250                         pstring rest;
251
252                         /* Stat failed - ensure we don't use it. */
253                         ZERO_STRUCT(st);
254                         *rest = 0;
255
256                         /*
257                          * Remember the rest of the pathname so it can be restored
258                          * later.
259                          */
260
261                         if (end)
262                                 pstrcpy(rest,end+1);
263
264                         /*
265                          * Try to find this part of the path in the directory.
266                          */
267
268                         if (ms_has_wild(start) || 
269                             !scan_directory(dirpath, start, 
270                                             sizeof(pstring) - 1 - (start - name), 
271                                             conn, 
272                                             end?True:False)) {
273                                 if (end) {
274                                         /*
275                                          * An intermediate part of the name can't be found.
276                                          */
277                                         DEBUG(5,("Intermediate not found %s\n",start));
278                                         *end = '/';
279
280                                         /* 
281                                          * We need to return the fact that the intermediate
282                                          * name resolution failed. This is used to return an
283                                          * error of ERRbadpath rather than ERRbadfile. Some
284                                          * Windows applications depend on the difference between
285                                          * these two errors.
286                                          */
287                                         *bad_path = True;
288                                         return(False);
289                                 }
290               
291                                 /* 
292                                  * Just the last part of the name doesn't exist.
293                                  * We may need to strupper() or strlower() it in case
294                                  * this conversion is being used for file creation 
295                                  * purposes. If the filename is of mixed case then 
296                                  * don't normalise it.
297                                  */
298
299                                 if (!conn->case_preserve && (!strhasupper(start) || !strhaslower(start)))               
300                                         strnorm(start, lp_defaultcase(SNUM(conn)));
301
302                                 /*
303                                  * check on the mangled stack to see if we can recover the 
304                                  * base of the filename.
305                                  */
306
307                                 if (mangle_is_mangled(start)) {
308                                         mangle_check_cache( start );
309                                 }
310
311                                 DEBUG(5,("New file %s\n",start));
312                                 return(True); 
313                         }
314
315                         /* 
316                          * Restore the rest of the string. If the string was mangled the size
317                          * may have changed.
318                          */
319                         if (end) {
320                                 end = start + strlen(start);
321                                 if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) ||
322                                     !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) {
323                                         return False;
324                                 }
325                                 *end = '\0';
326                         } else {
327                                 /*
328                                  * We just scanned for, and found the end of the path.
329                                  * We must return a valid stat struct if it exists.
330                                  * JRA.
331                                  */
332
333                                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
334                                         *pst = st;
335                                 } else {
336                                         ZERO_STRUCT(st);
337                                 }
338                         }
339                 } /* end else */
340
341                 /* 
342                  * Add to the dirpath that we have resolved so far.
343                  */
344                 if (*dirpath)
345                         pstrcat(dirpath,"/");
346
347                 pstrcat(dirpath,start);
348
349                 /*
350                  * Don't cache a name with mangled or wildcard components
351                  * as this can change the size.
352                  */
353                 
354                 if(!component_was_mangled && !name_has_wildcard)
355                         stat_cache_add(orig_path, dirpath, conn->case_sensitive);
356         
357                 /* 
358                  * Restore the / that we wiped out earlier.
359                  */
360                 if (end)
361                         *end = '/';
362         }
363   
364         /*
365          * Don't cache a name with mangled or wildcard components
366          * as this can change the size.
367          */
368
369         if(!component_was_mangled && !name_has_wildcard)
370                 stat_cache_add(orig_path, name, conn->case_sensitive);
371
372         /* 
373          * The name has been resolved.
374          */
375
376         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
377         return(True);
378 }
379
380 /****************************************************************************
381  Check a filename - possibly caling reducename.
382  This is called by every routine before it allows an operation on a filename.
383  It does any final confirmation necessary to ensure that the filename is
384  a valid one for the user to access.
385 ****************************************************************************/
386
387 BOOL check_name(pstring name,connection_struct *conn)
388 {
389         BOOL ret = True;
390
391         errno = 0;
392
393         if (IS_VETO_PATH(conn, name))  {
394                 /* Is it not dot or dot dot. */
395                 if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
396                         DEBUG(5,("file path name %s vetoed\n",name));
397                         return False;
398                 }
399         }
400
401         if (!lp_widelinks(SNUM(conn))) {
402                 ret = reduce_name(conn,name);
403         }
404
405         /* Check if we are allowing users to follow symlinks */
406         /* Patch from David Clerc <David.Clerc@cui.unige.ch>
407                 University of Geneva */
408
409 #ifdef S_ISLNK
410         if (!lp_symlinks(SNUM(conn))) {
411                 SMB_STRUCT_STAT statbuf;
412                 if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) &&
413                                 (S_ISLNK(statbuf.st_mode)) ) {
414                         DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
415                         ret = False; 
416                 }
417         }
418 #endif
419
420         if (!ret)
421                 DEBUG(5,("check_name on %s failed\n",name));
422
423         return(ret);
424 }
425
426 /****************************************************************************
427  Scan a directory to find a filename, matching without case sensitivity.
428  If the name looks like a mangled name then try via the mangling functions
429 ****************************************************************************/
430
431 static BOOL scan_directory(const char *path, char *name, size_t maxlength, 
432                            connection_struct *conn,BOOL docache)
433 {
434         void *cur_dir;
435         const char *dname;
436         BOOL mangled;
437
438         mangled = mangle_is_mangled(name);
439
440         /* handle null paths */
441         if (*path == 0)
442                 path = ".";
443
444         if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
445                 safe_strcpy(name, dname, maxlength);    
446                 return(True);
447         }      
448
449         /*
450          * The incoming name can be mangled, and if we de-mangle it
451          * here it will not compare correctly against the filename (name2)
452          * read from the directory and then mangled by the mangle_map()
453          * call. We need to mangle both names or neither.
454          * (JRA).
455          */
456         if (mangled)
457                 mangled = !mangle_check_cache( name );
458
459         /* open the directory */
460         if (!(cur_dir = OpenDir(conn, path, True))) {
461                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
462                 return(False);
463         }
464
465         /* now scan for matching names */
466         while ((dname = ReadDirName(cur_dir))) {
467
468                 /* Is it dot or dot dot. */
469                 if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) {
470                         continue;
471                 }
472
473                 /*
474                  * At this point dname is the unmangled name.
475                  * name is either mangled or not, depending on the state of the "mangled"
476                  * variable. JRA.
477                  */
478
479                 /*
480                  * Check mangled name against mangled name, or unmangled name
481                  * against unmangled name.
482                  */
483
484                 if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) {
485                         /* we've found the file, change it's name and return */
486                         if (docache)
487                                 DirCacheAdd(path,name,dname,SNUM(conn));
488                         safe_strcpy(name, dname, maxlength);
489                         CloseDir(cur_dir);
490                         return(True);
491                 }
492         }
493
494         CloseDir(cur_dir);
495         return(False);
496 }