You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Jim Rudnicki <jd...@pacbell.net> on 2000/07/03 09:57:43 UTC

Patch suggestion for org.apache.tomcat.util.FileUtil.java

In v3.1, Context.getRealPath() did not work for subdirectories.  The
workaround was to
use "dot" as in:

 getContext().getRealPath( "./subdir/file.xhtml" )

which would retrieve for example:

 c:/tomcat/webapps/context/./subdir/file.xhtml

On Windows, this was an effective workaround.

The new version, 3.2b1, breaks this.  The failing occurs in a security check
in
org.apache.tomcat.util.FileUtil.java at around line 152.  A comparison is
made with the canonical path, which for the above
example would be

 c:/tomcat/webapps/context/subdir/file.xhtml

and subsequently fails

This is the section of code that determines that the above example is
unsafe:

    try {
      canPath=new File(realPath).getCanonicalPath();
    } catch( IOException ex ) {
      ex.printStackTrace();
      return null;
    }


// This absPath/canPath comparison plugs security holes...
// On Windows, makes "x.jsp.", "x.Jsp", and "x.jsp%20"
// return 404 instead of the JSP source
// On all platforms, makes sure we don't let ../'s through
// Unfortunately, on Unix, it prevents symlinks from working
// So, a check for File.separatorChar='\\' ..... It hopefully
// happens on flavors of Windows.
 if (File.separatorChar  == '\\') {
     // On Windows check ignore case....
     if (!realPath.equalsIgnoreCase(canPath)){
            int ls=realPath.lastIndexOf('\\');
            if ( (ls > 0) &&
!realPath.substring(0,ls).equalsIgnoreCase(canPath) )
          return null;
     }
 }



I believe the following patch to the beginning of this method provide
correct behavior
without compomising the security check.  It works for me on Win98/Sun
JDK1.1.8.
Don't see why it would introduce a problem elsewhere:

  public static String safePath( String base, String path ) {

    /* Convert to one separator type */
    String normP=path;
    if( path.indexOf('\\') >=0 ) {
      normP= path.replace('\\', '/');
    }

    /* Remove inconsequential "current directory" part
    from path.  Without this, check will unfairly fail the
    safety check below ( canonical==real )
    Do this after all separators have been converted
    above. */
    if( normP.startsWith("./") ) {
      normP = normP.substring(2);
    }

    // Hack for Jsp ( and other servlets ) that use rel. paths
    if( ! normP.startsWith("/") ) {
      normP="/"+ normP;
    }

    String realPath= base + normP;

'nite,
Jim