Veto files fix.
authorJeremy Allison <jra@samba.org>
Thu, 13 Jun 2002 21:20:51 +0000 (21:20 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 13 Jun 2002 21:20:51 +0000 (21:20 +0000)
Jeremy.
(This used to be commit 1712a7b34a73ad89965961c0db4dd198d6b257c6)

source3/smbd/filename.c

index 522163d8e1bd7008b5e3182b9a905d96e39a1c4b..e5f9b7a0ae8588d95177d7dc93cb6968f9e5c385 100644 (file)
@@ -48,7 +48,6 @@ static BOOL fname_equal(char *name1, char *name2)
        return(strequal(name1,name2));
 }
 
-
 /****************************************************************************
  Mangle the 2nd name and check if it is then equal to the first name.
 ****************************************************************************/
@@ -62,7 +61,6 @@ static BOOL mangled_equal(char *name1, const char *name2, int snum)
        return strequal(name1, tmpname);
 }
 
-
 /****************************************************************************
 This routine is called to convert names from the dos namespace to unix
 namespace. It needs to handle any case conversions, mangling, format
@@ -93,284 +91,282 @@ for nlinks = 0, which can never be true for any file).
 BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, 
                   BOOL *bad_path, SMB_STRUCT_STAT *pst)
 {
-  SMB_STRUCT_STAT st;
-  char *start, *end;
-  pstring dirpath;
-  pstring orig_path;
-  BOOL component_was_mangled = False;
-  BOOL name_has_wildcard = False;
-
-  ZERO_STRUCTP(pst);
-
-  *dirpath = 0;
-  *bad_path = False;
-  if(saved_last_component)
-    *saved_last_component = 0;
-
-  if (conn->printer) {
-         /* we don't ever use the filenames on a printer share as a
-            filename - so don't convert them */
-         return True;
-  }
-
-  DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
-
-  /* 
-   * Convert to basic unix format - removing \ chars and cleaning it up.
-   */
-
-  unix_format(name);
-  unix_clean_name(name);
-
-  /* 
-   * Names must be relative to the root of the service - trim any leading /.
-   * also trim trailing /'s.
-   */
-
-  trim_string(name,"/","/");
-
-  /*
-   * If we trimmed down to a single '\0' character
-   * then we should use the "." directory to avoid
-   * searching the cache, but not if we are in a
-   * printing share.
-   */
-
-  if (!*name) {
-    name[0] = '.';
-    name[1] = '\0';
-  }
-
-  /*
-   * Ensure saved_last_component is valid even if file exists.
-   */
-
-  if(saved_last_component) {
-    end = strrchr_m(name, '/');
-    if(end)
-      pstrcpy(saved_last_component, end + 1);
-    else
-      pstrcpy(saved_last_component, name);
-  }
-
-  if (!case_sensitive && 
-      (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve)))
-    strnorm(name);
-
-  /*
-   * If we trimmed down to a single '\0' character
-   * then we will be using the "." directory.
-   * As we know this is valid we can return true here.
-   */
-
-  if(!*name)
-    return(True);
-
-  start = name;
-  while (strncmp(start,"./",2) == 0)
-    start += 2;
-
-  pstrcpy(orig_path, name);
-
-  if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
-    *pst = st;
-    return True;
-  }
-
-  /* 
-   * stat the name - if it exists then we are all done!
-   */
-
-/* ZZZ: stat1 */  if (vfs_stat(conn,name,&st) == 0) {
-    stat_cache_add(orig_path, name);
-    DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
-    *pst = st;
-    return(True);
-  }
-
-  DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
-        name, dirpath, start));
-
-  /* 
-   * A special case - if we don't have any mangling chars and are case
-   * sensitive then searching won't help.
-   */
-
-  if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map)
-    return(False);
-
-  name_has_wildcard = ms_has_wild(start);
-
-  /* 
-   * is_mangled() was changed to look at an entire pathname, not 
-   * just a component. JRA.
-   */
-
-  if (mangle_is_mangled(start))
-    component_was_mangled = True;
-
-  /* 
-   * Now we need to recursively match the name against the real 
-   * directory structure.
-   */
-
-  /* 
-   * Match each part of the path name separately, trying the names
-   * as is first, then trying to scan the directory for matching names.
-   */
-
-  for (; start ; start = (end?end+1:(char *)NULL)) {
-      /* 
-       * Pinpoint the end of this section of the filename.
-       */
-      end = strchr_m(start, '/');
-
-      /* 
-       * Chop the name at this point.
-       */
-      if (end) 
-        *end = 0;
-
-      if(saved_last_component != 0)
-        pstrcpy(saved_last_component, end ? end + 1 : start);
-
-      /* 
-       * Check if the name exists up to this point.
-       */
-
-      if (vfs_stat(conn,name, &st) == 0) {
-        /*
-         * It exists. it must either be a directory or this must be
-         * the last part of the path for it to be OK.
-         */
-        if (end && !(st.st_mode & S_IFDIR)) {
-          /*
-           * An intermediate part of the name isn't a directory.
-            */
-          DEBUG(5,("Not a dir %s\n",start));
-          *end = '/';
-          return(False);
-        }
-
-      } else {
-        pstring rest;
-
-        /* Stat failed - ensure we don't use it. */
-        ZERO_STRUCT(st);
-        *rest = 0;
-
-        /*
-         * Remember the rest of the pathname so it can be restored
-         * later.
-         */
-
-        if (end)
-          pstrcpy(rest,end+1);
-
-        /*
-         * Try to find this part of the path in the directory.
-         */
-
-        if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) {
-          if (end) {
-            /*
-             * An intermediate part of the name can't be found.
-             */
-            DEBUG(5,("Intermediate not found %s\n",start));
-            *end = '/';
-
-            /* 
-             * We need to return the fact that the intermediate
-             * name resolution failed. This is used to return an
-             * error of ERRbadpath rather than ERRbadfile. Some
-             * Windows applications depend on the difference between
-             * these two errors.
-             */
-            *bad_path = True;
-            return(False);
-          }
+       SMB_STRUCT_STAT st;
+       char *start, *end;
+       pstring dirpath;
+       pstring orig_path;
+       BOOL component_was_mangled = False;
+       BOOL name_has_wildcard = False;
+
+       ZERO_STRUCTP(pst);
+
+       *dirpath = 0;
+       *bad_path = False;
+       if(saved_last_component)
+               *saved_last_component = 0;
+
+       if (conn->printer) {
+               /* we don't ever use the filenames on a printer share as a
+                       filename - so don't convert them */
+               return True;
+       }
+
+       DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
+
+       /* 
+        * Convert to basic unix format - removing \ chars and cleaning it up.
+        */
+
+       unix_format(name);
+       unix_clean_name(name);
+
+       /* 
+        * Names must be relative to the root of the service - trim any leading /.
+        * also trim trailing /'s.
+        */
+
+       trim_string(name,"/","/");
+
+       /*
+        * If we trimmed down to a single '\0' character
+        * then we should use the "." directory to avoid
+        * searching the cache, but not if we are in a
+        * printing share.
+        */
+
+       if (!*name) {
+               name[0] = '.';
+               name[1] = '\0';
+       }
+
+       /*
+        * Ensure saved_last_component is valid even if file exists.
+        */
+
+       if(saved_last_component) {
+               end = strrchr_m(name, '/');
+               if(end)
+                       pstrcpy(saved_last_component, end + 1);
+               else
+                       pstrcpy(saved_last_component, name);
+       }
+
+       if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve)))
+               strnorm(name);
+
+       /*
+        * If we trimmed down to a single '\0' character
+        * then we will be using the "." directory.
+        * As we know this is valid we can return true here.
+        */
+
+       if(!*name)
+               return(True);
+
+       start = name;
+       while (strncmp(start,"./",2) == 0)
+               start += 2;
+
+       pstrcpy(orig_path, name);
+
+       if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
+               *pst = st;
+               return True;
+       }
+
+       /* 
+        * stat the name - if it exists then we are all done!
+        */
+
+       if (vfs_stat(conn,name,&st) == 0) {
+               stat_cache_add(orig_path, name);
+               DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
+               *pst = st;
+               return(True);
+       }
+
+       DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
+
+       /* 
+        * A special case - if we don't have any mangling chars and are case
+        * sensitive then searching won't help.
+        */
+
+       if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map)
+               return(False);
+
+       name_has_wildcard = ms_has_wild(start);
+
+       /* 
+        * is_mangled() was changed to look at an entire pathname, not 
+        * just a component. JRA.
+        */
+
+       if (mangle_is_mangled(start))
+               component_was_mangled = True;
+
+       /* 
+        * Now we need to recursively match the name against the real 
+        * directory structure.
+        */
+
+       /* 
+        * Match each part of the path name separately, trying the names
+        * as is first, then trying to scan the directory for matching names.
+        */
+
+       for (; start ; start = (end?end+1:(char *)NULL)) {
+               /* 
+                * Pinpoint the end of this section of the filename.
+                */
+               end = strchr_m(start, '/');
+
+               /* 
+                * Chop the name at this point.
+                */
+               if (end) 
+                       *end = 0;
+
+               if(saved_last_component != 0)
+                       pstrcpy(saved_last_component, end ? end + 1 : start);
+
+               /* 
+                * Check if the name exists up to this point.
+                */
+
+               if (vfs_stat(conn,name, &st) == 0) {
+                       /*
+                        * It exists. it must either be a directory or this must be
+                        * the last part of the path for it to be OK.
+                        */
+                       if (end && !(st.st_mode & S_IFDIR)) {
+                               /*
+                                * An intermediate part of the name isn't a directory.
+                                */
+                               DEBUG(5,("Not a dir %s\n",start));
+                               *end = '/';
+                               return(False);
+                       }
+
+               } else {
+                       pstring rest;
+
+                       /* Stat failed - ensure we don't use it. */
+                       ZERO_STRUCT(st);
+                       *rest = 0;
+
+                       /*
+                        * Remember the rest of the pathname so it can be restored
+                        * later.
+                        */
+
+                       if (end)
+                               pstrcpy(rest,end+1);
+
+                       /*
+                        * Try to find this part of the path in the directory.
+                        */
+
+                       if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) {
+                               if (end) {
+                                       /*
+                                        * An intermediate part of the name can't be found.
+                                        */
+                                       DEBUG(5,("Intermediate not found %s\n",start));
+                                       *end = '/';
+
+                                       /* 
+                                        * We need to return the fact that the intermediate
+                                        * name resolution failed. This is used to return an
+                                        * error of ERRbadpath rather than ERRbadfile. Some
+                                        * Windows applications depend on the difference between
+                                        * these two errors.
+                                        */
+                                       *bad_path = True;
+                                       return(False);
+                               }
              
-          /* 
-           * Just the last part of the name doesn't exist.
-           * We may need to strupper() or strlower() it in case
-           * this conversion is being used for file creation 
-           * purposes. If the filename is of mixed case then 
-           * don't normalise it.
-           */
-
-          if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))          
-            strnorm(start);
-
-          /*
-           * check on the mangled stack to see if we can recover the 
-           * base of the filename.
-           */
-
-          if (mangle_is_mangled(start)) {
-                 mangle_check_cache( start );
-          }
-
-          DEBUG(5,("New file %s\n",start));
-          return(True); 
-        }
-
-      /* 
-       * Restore the rest of the string. If the string was mangled the size
-       * may have changed.
-       */
-      if (end) {
-        end = start + strlen(start);
-        pstrcat(start,"/");
-        pstrcat(start,rest);
-        *end = '\0';
-      }
-    } /* end else */
-
-    /* 
-     * Add to the dirpath that we have resolved so far.
-     */
-    if (*dirpath)
-      pstrcat(dirpath,"/");
-
-    pstrcat(dirpath,start);
-
-    /*
-     * Don't cache a name with mangled or wildcard components
-     * as this can change the size.
-     */
-
-    if(!component_was_mangled && !name_has_wildcard)
-      stat_cache_add(orig_path, dirpath);
-
-    /* 
-     * Restore the / that we wiped out earlier.
-     */
-    if (end)
-      *end = '/';
-  }
+                               /* 
+                                * Just the last part of the name doesn't exist.
+                                * We may need to strupper() or strlower() it in case
+                                * this conversion is being used for file creation 
+                                * purposes. If the filename is of mixed case then 
+                                * don't normalise it.
+                                */
+
+                               if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))             
+                                       strnorm(start);
+
+                               /*
+                                * check on the mangled stack to see if we can recover the 
+                                * base of the filename.
+                                */
+
+                               if (mangle_is_mangled(start)) {
+                                       mangle_check_cache( start );
+                               }
+
+                               DEBUG(5,("New file %s\n",start));
+                               return(True); 
+                       }
+
+                       /* 
+                        * Restore the rest of the string. If the string was mangled the size
+                        * may have changed.
+                        */
+                       if (end) {
+                               end = start + strlen(start);
+                               pstrcat(start,"/");
+                               pstrcat(start,rest);
+                               *end = '\0';
+                       }
+               } /* end else */
+
+               /* 
+                * Add to the dirpath that we have resolved so far.
+                */
+               if (*dirpath)
+                       pstrcat(dirpath,"/");
+
+               pstrcat(dirpath,start);
+
+               /*
+                * Don't cache a name with mangled or wildcard components
+                * as this can change the size.
+                */
+               
+               if(!component_was_mangled && !name_has_wildcard)
+                       stat_cache_add(orig_path, dirpath);
+       
+               /* 
+                * Restore the / that we wiped out earlier.
+                */
+               if (end)
+                       *end = '/';
+       }
   
-  /*
-   * Don't cache a name with mangled or wildcard components
-   * as this can change the size.
-   */
+       /*
+        * Don't cache a name with mangled or wildcard components
+        * as this can change the size.
+        */
 
-  if(!component_was_mangled && !name_has_wildcard)
-    stat_cache_add(orig_path, name);
+       if(!component_was_mangled && !name_has_wildcard)
+               stat_cache_add(orig_path, name);
 
-  /*
-   * If we ended up resolving the entire path then return a valid
-   * stat struct if we got one.
-   */
+       /*
+        * If we ended up resolving the entire path then return a valid
+        * stat struct if we got one.
+        */
 
-  if (VALID_STAT(st) && (strlen(orig_path) == strlen(name)))
-    *pst = st;
+       if (VALID_STAT(st) && (strlen(orig_path) == strlen(name)))
+               *pst = st;
 
-  /* 
-   * The name has been resolved.
-   */
+       /* 
+        * The name has been resolved.
+        */
 
-  DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
-  return(True);
+       DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
+       return(True);
 }
 
 /****************************************************************************
@@ -387,8 +383,10 @@ BOOL check_name(char *name,connection_struct *conn)
        errno = 0;
 
        if (IS_VETO_PATH(conn, name))  {
-               DEBUG(5,("file path name %s vetoed\n",name));
-               return(0);
+               if(strcmp(name, ".") && strcmp(name, "..")) {
+                       DEBUG(5,("file path name %s vetoed\n",name));
+                       return(0);
+               }
        }
 
        ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn)));