summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/filename.c548
1 files changed, 273 insertions, 275 deletions
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 522163d8e1..e5f9b7a0ae 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -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)));